sql >> Base de Datos >  >> RDS >> Mysql

MySQL:¿Cómo hacer una consulta de rango de IP más rápida? GeoIP

Estaba lidiando con un problema similar, donde tenía que buscar en una base de datos con aproximadamente 4 millones de rangos de IP y encontré una buena solución que redujo la cantidad de filas escaneadas de 4 millones a aproximadamente ~ 5 (dependiendo de la IP):

Esta instrucción SQL:

SELECT id FROM geoip WHERE $iplong BETWEEN range_begin AND range_end 

se transforma en:

SELECT id FROM geoip WHERE range_begin <= $iplong AND range_end >= $iplong 

El problema es que MySQL recupera todas las filas con 'range_begin <=$iplong' y luego necesita escanear si 'range_end>=$iplong'. Esta primera condición AND (range_begin <=$iplong) recuperó alrededor de 2 millones de filas, y todas deben verificarse si range_end coincide.

Sin embargo, esto se puede simplificar drásticamente agregando una condición AND:

SELECT id FROM geoip WHERE range_begin <= $iplong AND range_begin >= $iplong-65535 AND range_end >= $iplong 

La declaración

range_begin <= $iplong AND range_begin >= $iplong-65535

recupera solo entradas donde range_begin está entre $iplong-65535 y $iplong. En mi caso, esto redujo el número de filas recuperadas de 4 Mio. a alrededor de 5 y el tiempo de ejecución del script se redujo de varios minutos a unos pocos segundos.

Nota sobre 65535 :Esta es para mi tabla la distancia máxima entre range_begin y range_end, es decir, (range_end-range_begin) <=65535 para todas mis filas. Si tiene rangos de IP más grandes, debe aumentar el 65535, si tiene rangos de IP más pequeños, puede disminuir esta constante. Si esta constante es demasiado grande (por ejemplo, 4 mil millones), no ahorrará tiempo de consulta.

Para esta consulta, solo necesita un índice en range_begin.