sql >> Database >  >> RDS >> Mysql

MySQL:Hoe maak je een snellere IP-bereikquery? GeoIP

Ik had te maken met een soortgelijk probleem, waarbij ik een database met ongeveer 4 miljoen IP-bereiken moest doorzoeken en een mooie oplossing vond die het aantal gescande rijen terugbracht van 4 miljoen naar ongeveer ~5 (afhankelijk van het IP):

Deze SQL-instructie:

SELECT id FROM geoip WHERE $iplong BETWEEN range_begin AND range_end 

wordt getransformeerd naar:

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

Het probleem is dat MySQL alle rijen met 'range_begin <=$iplong' ophaalt en vervolgens moet scannen als 'range_end>=$iplong'. Deze eerste AND-voorwaarde (range_begin <=$iplong) heeft ongeveer 2 miljoen rijen opgehaald en ze moeten allemaal worden gecontroleerd of range_end overeenkomt.

Dit kan echter drastisch worden vereenvoudigd door één EN-voorwaarde toe te voegen:

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

De verklaring

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

haalt alleen items op waarvan de range_begin tussen $iplong-65535 en $iplong ligt. In mijn geval verminderde dit het aantal opgehaalde rijen van 4 miljoen. tot ongeveer 5 en de runtime van het script daalde van meerdere minuten tot een paar seconden.

Opmerking over 65535 :Dit is voor mijn tabel de maximale afstand tussen range_begin en range_end, d.w.z. (range_end-range_begin) <=65535 voor al mijn rijen. Als je grotere IP-bereiken hebt, moet je de 65535 verhogen, als je kleinere IP-bereiken hebt, kun je deze constante verlagen. Als deze constante te groot is (bijvoorbeeld 4 miljard), bespaart u geen zoektijd.

Voor deze zoekopdracht heeft u alleen een index op range_begin nodig.



  1. PayPal POST-gegevens na succesvolle betaling

  2. Over SQLite

  3. GROUP BY vs ORDER BY

  4. IN-clausule met NULL of IS NULL