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í proSELECT * ... 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.