Pamiętaj, że adresy IP to nie adres tekstowy, ale numeryczny identyfikator. Mam podobną sytuację (robimy wyszukiwania geo-ip) i jeśli przechowujesz wszystkie swoje adresy IP jako liczby całkowite (na przykład mój adres IP to 192.115.22.33, więc jest przechowywany jako 3228767777), możesz wyszukać adresy IP łatwo, używając operatorów zmiany prawej.
Wadą wszystkich tych typów wyszukiwań jest to, że nie można czerpać korzyści z indeksów i za każdym razem, gdy wykonujesz wyszukiwanie, musisz wykonać pełne skanowanie tabeli. Powyższy schemat można ulepszyć przechowując zarówno adres IP sieci CIDR (początek zakresu) jak i adres rozgłoszeniowy (koniec zakresu), więc na przykład do przechowywania 192.168.1.0/24 można przechowywać dwa kolumny:
network broadcast
3232235776, 3232236031
A potem możesz go dopasować, po prostu to zrobisz
SELECT count(*) FROM bans WHERE 3232235876 >= network AND 3232235876 <= broadcast
Umożliwiłoby to przechowywanie sieci CIDR w bazie danych i szybkie i wydajne dopasowywanie ich do adresów IP, korzystając z szybkich indeksów numerycznych.
Notatka z dyskusji poniżej :
MySQL 5.0 zawiera optymalizację zapytań zakresowych o nazwie „indeks przecięcie scalania " co pozwala przyspieszyć takie zapytania (i uniknąć pełnego skanowania tabeli), o ile:
- Istnieje wielokolumnowy indeks, który odpowiada dokładnie kolumnom w zapytaniu, w kolejności. Tak więc - dla powyższego przykładu zapytania indeks musiałby mieć postać
(network, broadcast)
. - Wszystkie dane można pobrać z indeksu. Dotyczy to
COUNT(*)
, ale nie jest prawdziwe dlaSELECT * ... LIMIT 1
.
MySQL 5.6 zawiera optymalizację o nazwie MRR, która również przyspieszyłaby pobieranie pełnych wierszy, ale jest to poza zakresem tej odpowiedzi.