Saya berurusan dengan masalah serupa, di mana saya harus mencari database dengan sekitar 4 Juta rentang IP dan menemukan solusi bagus yang menurunkan jumlah baris yang dipindai dari 4 Juta menjadi sekitar ~5 (tergantung IP):
Pernyataan SQL ini:
SELECT id FROM geoip WHERE $iplong BETWEEN range_begin AND range_end
diubah menjadi:
SELECT id FROM geoip WHERE range_begin <= $iplong AND range_end >= $iplong
Masalahnya adalah MySQL mengambil semua baris dengan 'range_begin <=$iplong' dan kemudian perlu memindai jika 'range_end>=$iplong'. Kondisi AND pertama ini (range_begin <=$iplong) mengambil sekitar 2 Juta baris, dan semuanya perlu diperiksa apakah range_end cocok.
Namun ini dapat disederhanakan secara dramatis dengan menambahkan satu kondisi DAN:
SELECT id FROM geoip WHERE range_begin <= $iplong AND range_begin >= $iplong-65535 AND range_end >= $iplong
Pernyataan
range_begin <= $iplong AND range_begin >= $iplong-65535
hanya mengambil entri dengan range_begin antara $iplong-65535 dan $iplong. Dalam kasus saya, ini mengurangi jumlah baris yang diambil dari 4 Mio. menjadi sekitar 5 dan waktu proses skrip turun dari beberapa menit menjadi beberapa detik.
Catatan di 65535 :Ini untuk meja saya jarak maksimal antara range_begin dan range_end, mis., (range_end-range_begin) <=65535 untuk semua baris saya. Jika Anda memiliki rentang IP yang lebih besar, Anda harus meningkatkan 65535, jika Anda memiliki rentang IP yang lebih kecil, Anda dapat mengurangi konstanta ini. Jika konstanta ini terlalu besar (misalnya 4 Miliar), Anda tidak akan menghemat waktu kueri.
Untuk kueri ini, Anda hanya memerlukan indeks pada range_begin.