Mysql
 sql >> Base de données >  >> RDS >> Mysql

Jointures sur les index mysql spatiaux

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