Я считаю, что это потому, что MySQL не поддерживает объединение пространственных индексов. Не уверен, что это все еще правда, но я читал это где-то в прошлом. Если у вас есть оператор OR, то пространственные индексы не используются
В вашем случае, где вы делаете points.id = 1, это прямой выбор с одним возвращенным результатом, который используется в mbrcontains. Это использует индекс.
Когда вы добавляете points.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 диапазоны, в которых содержится mbrcon (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