sql >> Databasteknik >  >> RDS >> Mysql

Finns det sätt att matcha IP med IP+CIDR ​​direkt från SELECT-frågan?

Kom ihåg att IP-adresser inte är en textadress, utan ett numeriskt ID. Jag har en liknande situation (vi gör geo-ip-sökningar), och om du lagrar alla dina IP-adresser som heltal (till exempel är min IP-adress 192.115.22.33 så den lagras som 3228767777), så kan du slå upp IP-adresser enkelt genom att använda högerskiftsoperatörer.

Nackdelen med alla dessa typer av uppslagningar är att du inte kan dra nytta av index och du måste göra en full tabellskanning när du gör en uppslagning. Ovanstående schema kan förbättras genom att lagra både nätverkets IP-adress för CIDR-nätverket (början av intervallet) och sändningsadressen (slutet av intervallet), så för att till exempel lagra 192.168.1.0/24 kan du lagra två kolumner:

network     broadcast
3232235776, 3232236031 

Och sedan kan du matcha det gör du helt enkelt

SELECT count(*) FROM bans WHERE 3232235876 >= network AND 3232235876 <= broadcast

Detta skulle låta dig lagra CIDR-nätverk i databasen och matcha dem mot IP-adresser snabbt och effektivt genom att dra fördel av snabba numeriska index.

Anteckning från diskussionen nedan :

MySQL 5.0 innehåller en optimering av intervallfrågor som heter "index merge intersect " som gör det möjligt att snabba upp sådana frågor (och undvika genomsökningar av hela tabeller), så länge som:

  • Det finns ett index med flera kolumner som matchar exakt kolumnerna i frågan, i ordning. Så - för frågeexemplet ovan skulle indexet behöva vara (network, broadcast) .
  • All data kan hämtas från indexet. Detta gäller för COUNT(*) , men är inte sant för SELECT * ... LIMIT 1 .

MySQL 5.6 innehåller en optimering som kallas MRR som också skulle påskynda hel radhämtning, men det ligger utanför omfattningen av detta svar.



  1. MySQL UPPDATERING och SELECT i ett pass

  2. Får ett udda fel, SQL Server-frågan använder "WITH"-satsen

  3. Skapa eller simulera tvådimensionella arrayer i PL/SQL

  4. Vad händer egentligen med det sökandet?