Eu estava lidando com um problema semelhante, onde tive que pesquisar um banco de dados com cerca de 4 milhões de intervalos de IP e encontrei uma boa solução que reduziu o número de linhas digitalizadas de 4 milhões para cerca de 5 (dependendo do IP):
Esta instrução SQL:
SELECT id FROM geoip WHERE $iplong BETWEEN range_begin AND range_end
é transformado em:
SELECT id FROM geoip WHERE range_begin <= $iplong AND range_end >= $iplong
O problema é que o MySQL recupera todas as linhas com 'range_begin <=$iplong' e então precisa escanear se 'range_end>=$iplong'. Essa primeira condição AND (range_begin <=$iplong) recuperou cerca de 2 milhões de linhas e todas precisam ser verificadas se range_end corresponder.
No entanto, isso pode ser simplificado drasticamente adicionando uma condição AND:
SELECT id FROM geoip WHERE range_begin <= $iplong AND range_begin >= $iplong-65535 AND range_end >= $iplong
A declaração
range_begin <= $iplong AND range_begin >= $iplong-65535
recupera apenas as entradas em que range_begin está entre $iplong-65535 e $iplong. No meu caso, isso reduziu o número de linhas recuperadas de 4 milhões. para cerca de 5 e o tempo de execução do script caiu de vários minutos para alguns segundos.
Observação sobre 65535 :Esta é para minha tabela a distância máxima entre range_begin e range_end, ou seja, (range_end-range_begin) <=65535 para todas as minhas linhas. Se você tiver intervalos de IP maiores, deverá aumentar o 65535, se tiver intervalos de IP menores, poderá diminuir essa constante. Se essa constante for muito grande (por exemplo, 4 bilhões), você não economizará tempo de consulta.
Para esta consulta, você só precisa de um índice em range_begin.