Ingat bahwa IP bukan alamat tekstual, tetapi ID numerik. Saya memiliki situasi yang sama (kami sedang melakukan pencarian geo-ip), dan jika Anda menyimpan semua alamat IP Anda sebagai bilangan bulat (misalnya, alamat IP saya adalah 192.115.22.33 sehingga disimpan sebagai 3228767777), maka Anda dapat mencari IP dengan mudah menggunakan operator shift kanan.
Kelemahan dari semua jenis pencarian ini adalah Anda tidak dapat memanfaatkan indeks dan Anda harus melakukan pemindaian tabel penuh setiap kali Anda melakukan pencarian. Skema di atas dapat ditingkatkan dengan menyimpan alamat IP jaringan dari jaringan CIDR (awal rentang) dan alamat broadcast (akhir rentang), jadi misalnya untuk menyimpan 192.168.1.0/24 Anda dapat menyimpan dua kolom:
network broadcast
3232235776, 3232236031
Dan kemudian Anda dapat mencocokkannya, Anda cukup melakukannya
SELECT count(*) FROM bans WHERE 3232235876 >= network AND 3232235876 <= broadcast
Ini akan memungkinkan Anda menyimpan jaringan CIDR dalam database dan mencocokkannya dengan alamat IP dengan cepat dan efisien dengan memanfaatkan indeks numerik cepat.
Catatan dari diskusi di bawah :
MySQL 5.0 menyertakan pengoptimalan kueri jarak jauh yang disebut "penggabungan indeks berpotongan " yang memungkinkan untuk mempercepat kueri tersebut (dan menghindari pemindaian tabel penuh), selama:
- Ada indeks multi-kolom yang sama persis dengan kolom dalam kueri, secara berurutan. Jadi - untuk contoh kueri di atas, indeksnya harus
(network, broadcast)
. - Semua data dapat diambil dari indeks. Ini berlaku untuk
COUNT(*)
, tetapi tidak benar untukSELECT * ... LIMIT 1
.
MySQL 5.6 menyertakan pengoptimalan yang disebut MRR yang juga akan mempercepat pengambilan baris penuh, tetapi itu di luar cakupan jawaban ini.