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

Existuje způsob, jak porovnat IP s IP + CIDR přímo z dotazu SELECT?

Pamatujte, že IP nejsou textová adresa, ale číselné ID. Mám podobnou situaci (provádíme vyhledávání geo-ip), a pokud ukládáte všechny své IP adresy jako celá čísla (například moje IP adresa je 192.115.22.33, takže je uložena jako 3228767777), můžete IP vyhledávat snadno pomocí operátorů posunu vpravo.

Nevýhodou všech těchto typů vyhledávání je, že nemůžete těžit z indexů a při každém vyhledávání musíte provést úplné skenování tabulky. Výše uvedené schéma lze vylepšit uložením jak síťové IP adresy sítě CIDR (začátek rozsahu), tak broadcast adresy (konec rozsahu), takže například pro uložení 192.168.1.0/24 můžete uložit dvě sloupce:

network     broadcast
3232235776, 3232236031 

A pak to můžete jednoduše spárovat

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

To vám umožní ukládat sítě CIDR do databáze a rychle a efektivně je porovnávat s IP adresami s využitím rychlých číselných indexů.

Poznámka z diskuse níže :

MySQL 5.0 zahrnuje optimalizaci dotazů s rozsahem nazvanou "sloučení indexu protínají " což umožňuje urychlit takové dotazy (a vyhnout se úplnému prohledávání tabulky), pokud:

  • Existuje vícesloupcový index, který přesně odpovídá sloupcům v dotazu v daném pořadí. Takže - pro výše uvedený příklad dotazu by index musel být (network, broadcast) .
  • Všechna data lze načíst z indexu. To platí pro COUNT(*) , ale neplatí pro SELECT * ... LIMIT 1 .

MySQL 5.6 obsahuje optimalizaci nazvanou MRR, která by také urychlila úplné načítání řádků, ale to je mimo rozsah této odpovědi.



  1. Výkon Oracle:Bulk Collect

  2. 5 užitečných dotazů MySql během vývoje projektu

  3. Postgres – Převeďte seznam sousedství na vnořený objekt JSON

  4. Jak můžete v SQL seskupit podle rozsahů?