sql >> Databasteknik >  >> RDS >> Mysql

MySQL:Hur gör man en snabbare IP-intervallfråga? GeoIP

Jag hade att göra med ett liknande problem, där jag var tvungen att söka i en databas med cirka 4 miljoner IP-intervall och hittade en bra lösning som minskade antalet skannade rader från 4 miljoner till cirka ~5 (beroende på IP):

Denna SQL-sats:

SELECT id FROM geoip WHERE $iplong BETWEEN range_begin AND range_end 

omvandlas till:

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

Problemet är att MySQL hämtar alla rader med 'range_begin <=$iplong' och måste sedan skanna om 'range_end>=$iplong'. Detta första AND-villkor (range_begin <=$iplong) hämtade cirka 2 miljoner rader, och alla måste kontrolleras om range_end matchar.

Detta kan dock förenklas dramatiskt genom att lägga till ett AND-villkor:

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

Uttalandet

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

hämtar endast poster där range_begin är mellan $iplong-65535 och $iplong. I mitt fall minskade detta antalet hämtade rader från 4 miljoner. till cirka 5 och skriptets körtid gick ner från flera minuter till några sekunder.

Anmärkning om 65535 :Detta är för min tabell det maximala avståndet mellan range_begin och range_end, dvs (range_end-range_begin) <=65535 för alla mina rader. Om du har större IP-intervall måste du öka 65535, om du har mindre IP-intervall kan du minska denna konstant. Om denna konstant är för stor (till exempel 4 miljarder), kommer du inte att spara någon frågetid.

För den här frågan behöver du bara ett index på range_begin.



  1. Jag vill kopiera en tabell från en databas och infoga den i en annan databastabell

  2. Oracle:laddar en stor xml-fil?

  3. få värden från tabellen endast för en specifik dag i mysql

  4. EAV över SQL Server