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 perSELECT * ... 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.