Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Gibt es eine Möglichkeit, IP direkt aus der SELECT-Abfrage mit IP + CIDR abzugleichen?

Denken Sie daran, dass IPs keine Textadressen sind, sondern eine numerische ID. Ich habe eine ähnliche Situation (wir führen Geo-IP-Lookups durch), und wenn Sie alle Ihre IP-Adressen als ganze Zahlen speichern (zum Beispiel ist meine IP-Adresse 192.115.22.33, also wird sie als 3228767777 gespeichert), dann können Sie IPs nachschlagen ganz einfach durch die Verwendung von Rechtsverschiebungsoperatoren.

Der Nachteil all dieser Suchtypen ist, dass Sie nicht von Indizes profitieren können und bei jeder Suche einen vollständigen Tabellenscan durchführen müssen. Das obige Schema kann verbessert werden, indem sowohl die Netzwerk-IP-Adresse des CIDR-Netzwerks (der Anfang des Bereichs) als auch die Broadcast-Adresse (das Ende des Bereichs) gespeichert werden. Um beispielsweise 192.168.1.0/24 zu speichern, können Sie zwei speichern Spalten:

network     broadcast
3232235776, 3232236031 

Und dann kannst du es einfach anpassen

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

Auf diese Weise können Sie CIDR-Netzwerke in der Datenbank speichern und sie schnell und effizient mit IP-Adressen abgleichen, indem Sie schnelle numerische Indizes nutzen.

Anmerkung aus der Diskussion unten :

MySQL 5.0 enthält eine Bereichsabfrageoptimierung namens „Index Merge Schnittpunkt ", was es erlaubt, solche Abfragen zu beschleunigen (und vollständige Tabellenscans zu vermeiden), solange:

  • Es gibt einen mehrspaltigen Index, der der Reihe nach genau mit den Spalten in der Abfrage übereinstimmt. Also - für das obige Abfragebeispiel müsste der Index (network, broadcast) sein .
  • Alle Daten können aus dem Index abgerufen werden. Dies gilt für COUNT(*) , gilt aber nicht für SELECT * ... LIMIT 1 .

MySQL 5.6 enthält eine Optimierung namens MRR, die auch den vollständigen Zeilenabruf beschleunigen würde, aber das ist außerhalb des Umfangs dieser Antwort.