Tôi tin rằng đó là vì MySQL không hỗ trợ hợp nhất các chỉ mục không gian. Không chắc nó có còn đúng không nhưng tôi đã đọc nó ở đâu đó trong quá khứ. Nếu bạn có câu lệnh OR, thì các chỉ mục không gian sẽ không được sử dụng
Trong trường hợp của bạn, bạn đang làm point.id =1 ở đâu, đó là một lựa chọn thẳng với một kết quả trả về được sử dụng trong mbrcontains. Điều đó sử dụng chỉ mục.
Khi bạn thêm điểm.in (1,2,3), kết quả đó trả về 3 kết quả và mỗi kết quả cần được ánh xạ vào bảng phạm vi, do đó không hoạt động
kết quả
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
Bạn có thể đơn giản hóa bài kiểm tra của mình mà không cần bảng điểm bằng cách thực hiện như sau:SELECT * FROM các phạm vi mà 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
Và bây giờ điều này; SELECT * FROM các phạm vi trong đó mbrcontains (poly, GEOMFROMWKB (POINT (0, 0))) HOẶC mbrcontains (poly, GEOMFROMWKB (POINT (10, 10)))
kết quả
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
Hãy thấy rằng trong trường hợp thứ hai, bạn không sử dụng chỉ mục và chỉ quét.
Bạn có thể buộc truy vấn sử dụng chỉ mục bằng cách tạo UNION cho từng điểm cụ thể nhưng tôi không chắc liệu điều đó có nhanh hơn không. Tôi đã thực hiện một số thử nghiệm cục bộ và nó chậm hơn một chút so với truy vấn đầu tiên của bạn.
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
kết quả
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