You have two problems that are not easily solved.
- UUIDs are terribly 'random',
- The optimizer dos not understand that the from-to ranges do not overlap
But first, let's make sure you have the cache settings right. If you are using MyISAM, key_buffer_size
should be about 20% of available RAM. Or for InnoDB, innodb_buffer_pool_size
should be about 70% of available RAM. If you had small settings, this change would only move the problem from being I/O to being CPU. And it will not scale past when you cannot cache most of the table and its indexes in RAM. Reference
My blog explains why UUIDs are terrible for large indexes. That also provides a Stored Function to make the UUID smaller (BINARY(16)
), hence more cacheable; this will help with the I/O.
If you have "type-1" UUIDs (such as generated by MySQL), the blog also explains why, with the help of the Function, use of UUIDs can be scaled. But if it is some other flavor of UUID, and you must have at least one BTree (INDEX
or PRIMARY KEY
) with the UUID in it, your task is not scalable. Can you turn it into an AUTO_INCREMENT
? That would allow INSERTs
to be clumped at the 'end' of the table rather than randomly scattered around the table, thereby blowing out cache?
As for the ranges, you need to revamp the table to put only one of from/to in each row. This involves extra rows for the 'unowned' ranges. Then write a stored routine to use LIMIT 1
to prevent what you are seeing -- namely failure to effectively use any index. Another blog goes into the details, together with schema design and reference code for IPv4 (which might be what you are doing) and IPv6. My code is very scalable and eliminates the indexing problem you posed.