Не забравяйте, че IP адресите не са текстов адрес, а цифров идентификатор. Имам подобна ситуация (правим гео-IP търсения) и ако съхранявате всичките си IP адреси като цели числа (например моят IP адрес е 192.115.22.33, така че се съхранява като 3228767777), тогава можете да търсите IP адреси лесно чрез използване на оператори за смяна на дясно.
Недостатъкът на всички тези видове справки е, че не можете да се възползвате от индекси и трябва да правите пълно сканиране на таблицата всеки път, когато правите търсене. Горната схема може да бъде подобрена чрез съхраняване както на мрежовия IP адрес на мрежата CIDR (началото на диапазона), така и на излъчващия адрес (края на диапазона), така че например за съхраняване на 192.168.1.0/24 можете да съхранявате две колони:
network broadcast
3232235776, 3232236031
И тогава можете просто да го направите
SELECT count(*) FROM bans WHERE 3232235876 >= network AND 3232235876 <= broadcast
Това ще ви позволи да съхранявате CIDR мрежи в базата данни и да ги съпоставяте с IP адреси бързо и ефективно, като се възползвате от бързите цифрови индекси.
Бележка от дискусията по-долу :
MySQL 5.0 включва оптимизация на заявки с обхват, наречена "пресичане на сливане на индекси ", което позволява да се ускорят такива заявки (и да се избегне пълно сканиране на таблицата), стига:
- Има индекс с няколко колони, който съвпада точно с колоните в заявката по ред. Така че - за горния пример за заявка, индексът трябва да бъде
(network, broadcast)
. - Всички данни могат да бъдат извлечени от индекса. Това е вярно за
COUNT(*)
, но не е вярно заSELECT * ... LIMIT 1
.
MySQL 5.6 включва оптимизация, наречена MRR, която също би ускорила пълното извличане на ред, но това е извън обхвата на този отговор.