sql >> Databáze >  >> RDS >> Mysql

MySQL:Jak udělat rychlejší dotaz na rozsah IP? GeoIP

Řešil jsem podobný problém, kdy jsem musel prohledat databázi s asi 4 miliony rozsahů IP a našel pěkné řešení, které snížilo počet naskenovaných řádků ze 4 milionů na přibližně ~5 (v závislosti na IP):

Tento příkaz SQL:

SELECT id FROM geoip WHERE $iplong BETWEEN range_begin AND range_end 

se transformuje na:

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

Problém je v tom, že MySQL načte všechny řádky s 'range_begin <=$iplong' a poté potřebuje skenovat, pokud 'range_end>=$iplong'. Tato první podmínka AND (range_begin <=$iplong) načetla asi 2 miliony řádků a všechny je třeba zkontrolovat, pokud se range_end shoduje.

To však lze výrazně zjednodušit přidáním jedné podmínky AND:

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

Prohlášení

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

načte pouze záznamy, kde je range_begin mezi $iplong-65535 a $iplong. V mém případě to snížilo počet načtených řádků ze 4 milionů. na přibližně 5 a běh skriptu se zkrátil z několika minut na několik sekund.

Poznámka na 65535 :Toto je pro mou tabulku maximální vzdálenost mezi range_begin a range_end, tj. (range_end-range_begin) <=65535 pro všechny mé řádky. Pokud máte větší rozsahy IP, musíte zvýšit 65535, pokud máte menší rozsahy IP, můžete tuto konstantu snížit. Pokud je tato konstanta příliš velká (například 4 miliardy), neušetříte čas na dotaz.

Pro tento dotaz potřebujete pouze index na range_begin.



  1. Výkon SQL:WHERE vs. WHERE (ROW_NUMBER)

  2. Jak načtu Individual Div bez načtení celé stránky a zobrazení stavu načítání?

  3. NodeJS:Kde se připojit k databázi v kódu?

  4. Chyba Sloupec dotazu SQL neexistuje