Mysql
 sql >> Database >  >> RDS >> Mysql

C'è un modo per abbinare IP a IP+CIDR ​​direttamente dalla query SELECT?

Ricorda che gli IP non sono un indirizzo testuale, ma un ID numerico. Ho una situazione simile (stiamo eseguendo ricerche geo-ip) e se memorizzi tutti i tuoi indirizzi IP come numeri interi (ad esempio, il mio indirizzo IP è 192.115.22.33 quindi è memorizzato come 3228767777), puoi cercare IP facilmente utilizzando gli operatori del turno di destra.

Lo svantaggio di tutti questi tipi di ricerche è che non puoi trarre vantaggio dagli indici e devi eseguire una scansione completa della tabella ogni volta che esegui una ricerca. Lo schema sopra può essere migliorato memorizzando sia l'indirizzo IP di rete della rete CIDR (l'inizio dell'intervallo) che l'indirizzo di trasmissione (la fine dell'intervallo), quindi ad esempio per memorizzare 192.168.1.0/24 è possibile memorizzare due colonne:

network     broadcast
3232235776, 3232236031 

E poi puoi abbinarlo, lo fai semplicemente

SELECT count(*) FROM bans WHERE 3232235876 >= network AND 3232235876 <= broadcast

Ciò ti consente di archiviare le reti CIDR nel database e di confrontarle con gli indirizzi IP in modo rapido ed efficiente, sfruttando gli indici numerici rapidi.

Nota dalla discussione di seguito :

MySQL 5.0 include un'ottimizzazione delle query a intervalli denominata "unione indice interseca " che consente di velocizzare tali query (ed evitare scansioni complete della tabella), purché:

  • Esiste un indice a più colonne che corrisponde esattamente alle colonne della query, in ordine. Quindi, per l'esempio di query precedente, l'indice dovrebbe essere (network, broadcast) .
  • Tutti i dati possono essere recuperati dall'indice. Questo vale per COUNT(*) , ma non è vero per SELECT * ... LIMIT 1 .

MySQL 5.6 include un'ottimizzazione chiamata MRR che accelererebbe anche il recupero completo delle righe, ma non rientra nell'ambito di questa risposta.