Je pense que c'est parce que MySQL ne prend pas en charge la fusion des index spatiaux. Je ne sais pas si c'est toujours vrai mais je l'ai lu quelque part dans le passé. Si vous avez une instruction OR, les index spatiaux ne sont pas utilisés
Dans votre cas, où faites-vous points.id =1, c'est une sélection directe avec un résultat renvoyé qui est utilisé dans le mbrcontains. Qui utilise l'index.
Lorsque vous ajoutez points.in (1,2,3), cela renvoie 3 résultats et chacun doit être mappé à la table des plages, donc ne fonctionne pas
résultat
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
Vous pouvez simplifier votre test sans la table de points en procédant comme suit :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
Et maintenant ceci; SELECT * FROM plages où mbrcontains( poly, GEOMFROMWKB(POINT(0, 0))) OR mbrcontains( poly, GEOMFROMWKB(POINT(10, 10)))
résultat
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
Voyez que dans le second cas, vous n'utilisez pas l'index et juste la numérisation.
Vous pouvez forcer la requête à utiliser l'index en créant UNION pour chaque point spécifique, mais je ne sais pas si cela va être plus rapide. J'ai fait quelques tests localement et c'était un peu plus lent que votre première requête.
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
résultat
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