Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Existe uma maneira de combinar IP com IP + CIDR diretamente da consulta SELECT?


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 para SELECT * ... 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.