Saya percaya itu karena MySQL tidak mendukung penggabungan indeks spasial. Tidak yakin apakah itu masih benar tetapi saya pernah membacanya di suatu tempat di masa lalu. Jika Anda memiliki pernyataan OR, maka indeks spasial tidak digunakan
Dalam kasus Anda, di mana Anda melakukan poin.id =1, itu adalah pemilihan langsung dengan satu hasil yang dikembalikan yang digunakan dalam mbrcontains. Itu menggunakan indeks.
Saat Anda menambahkan points.in (1,2,3), yang mengembalikan 3 hasil dan masing-masing perlu dipetakan ke tabel rentang, oleh karena itu tidak berfungsi
hasil
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE points range PRIMARY PRIMARY 4 NULL 3 100.00 Using where
1 SIMPLE ranges ALL poly NULL NULL NULL 6467418 100.00
Anda dapat menyederhanakan pengujian Anda tanpa tabel poin dengan melakukan ini:SELECT * FROM ranges where mbrcontains( poly, GEOMFROMWKB(POINT(0, 0)))
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE ranges range poly poly 34 NULL 1 100.00 Using where
Dan sekarang ini; SELECT * FROM rentang di mana mbrcontains( poly, GEOMFROMWKB(POINT(0, 0))) OR mbrcontains( poly, GEOMFROMWKB(POINT(10, 10)))
hasil
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE ranges ALL poly NULL NULL NULL 6467418 100.00 Using where
Lihat bahwa dalam kasus kedua, Anda tidak menggunakan indeks dan hanya memindai.
Anda dapat memaksa kueri untuk menggunakan indeks dengan membuat UNION untuk setiap titik tertentu, tetapi saya tidak yakin apakah itu akan lebih cepat. Saya melakukan beberapa pengujian secara lokal dan itu sedikit lebih lambat dari kueri pertama Anda.
EXPLAIN EXTENDED
SELECT *
FROM points
FORCE INDEX (PRIMARY )
LEFT JOIN ranges
FORCE INDEX ( poly ) ON mbrcontains( poly, point )
WHERE points.id = 1
UNION DISTINCT
SELECT *
FROM points
FORCE INDEX (PRIMARY )
LEFT JOIN ranges
FORCE INDEX ( poly ) ON mbrcontains( poly, point )
WHERE points.id = 2
UNION DISTINCT
SELECT *
FROM points
FORCE INDEX (PRIMARY )
LEFT JOIN ranges
FORCE INDEX ( poly ) ON mbrcontains( poly, point )
WHERE points.id = 3
hasil
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY points const PRIMARY PRIMARY 4 const 1 100.00
1 PRIMARY ranges range poly poly 34 NULL 1 100.00 Using where
2 UNION points const PRIMARY PRIMARY 4 const 1 100.00
2 UNION ranges range poly poly 34 NULL 1 100.00 Using where
3 UNION points const PRIMARY PRIMARY 4 const 1 100.00
3 UNION ranges range poly poly 34 NULL 1 100.00 Using where
NULL UNION RESULT <union1,2,3> ALL NULL NULL NULL NULL NULL NULL