Lembre-se de que os IPs não são um endereço textual, mas um ID numérico. Eu tenho uma situação semelhante (estamos fazendo pesquisas geo-ip), e se você armazenar todos os seus endereços IP como números inteiros (por exemplo, meu endereço IP é 192.115.22.33, então ele é armazenado como 3228767777), então você pode pesquisar IPs facilmente usando operadores de deslocamento para a direita.
A desvantagem de todos esses tipos de pesquisas é que você não pode se beneficiar dos índices e precisa fazer uma varredura completa da tabela sempre que fizer uma pesquisa. O esquema acima pode ser melhorado armazenando o endereço IP da rede CIDR (o início do intervalo) e o endereço de transmissão (o final do intervalo), então, por exemplo, para armazenar 192.168.1.0/24 você pode armazenar dois colunas:
network broadcast
3232235776, 3232236031
E então você pode combiná-lo, basta fazer
SELECT count(*) FROM bans WHERE 3232235876 >= network AND 3232235876 <= broadcast
Isso permitiria armazenar redes CIDR no banco de dados e combiná-las com endereços IP de maneira rápida e eficiente, aproveitando os índices numéricos rápidos.
Nota da discussão abaixo :
O MySQL 5.0 inclui uma otimização de consulta variada chamada "intersecção de mesclagem de índice " que permite acelerar essas consultas (e evitar varreduras de tabela completas), desde que:
- Há um índice de várias colunas que corresponde exatamente às colunas na consulta, em ordem. Então - para o exemplo de consulta acima, o índice precisaria ser
(network, broadcast)
. - Todos os dados podem ser recuperados do índice. Isso vale para
COUNT(*)
, mas não é verdadeiro paraSELECT * ... LIMIT 1
.
O MySQL 5.6 inclui uma otimização chamada MRR que também aceleraria a recuperação de linha completa, mas isso está fora do escopo desta resposta.