Ответ 1
Я считаю, что это потому, что MySQL не поддерживает слияние пространственных индексов. Не уверен, что это правда, но я читал это где-то в прошлом. Если у вас есть инструкция OR, то пространственные индексы не используются
В вашем случае, где вы делаете point.id = 1, прямой выбор с одним результатом, который возвращается, который используется в mbrcontains. Это использует индекс.
Когда вы добавляете point.in(1,2,3), который возвращает 3 результата, и каждый из них должен быть отображен в таблицу диапазонов, поэтому не работает
результат
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
Вы можете упростить свой тест без таблицы точек, выполнив это: SELECT * FROM диапазоны, где 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
И теперь это; SELECT * FROM диапазоны, где mbrcontains (poly, GEOMFROMWKB (POINT (0, 0))) ИЛИ mbrcontains (poly, GEOMFROMWKB (POINT (10, 10)))
результат
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
Посмотрите, что во втором случае вы не используете индекс и просто сканирование.
Вы можете заставить запрос использовать индекс, создавая UNION для каждой конкретной точки, но я не уверен, что это будет быстрее. Я сделал несколько тестов локально, и это было немного медленнее, чем ваш первый запрос.
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
результат
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