Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Joins auf räumlichen MySQL-Indizes

Ich glaube, das liegt daran, dass MySQL das Zusammenführen räumlicher Indizes nicht unterstützt. Ich bin mir nicht sicher, ob es noch stimmt, aber ich habe es irgendwo in der Vergangenheit gelesen. Wenn Sie eine ODER-Anweisung haben, werden die räumlichen Indizes nicht verwendet

In Ihrem Fall, wo Sie Punkte machen.id =1, das ist eine direkte Auswahl mit einem zurückgegebenen Ergebnis, das in den mbrcontains verwendet wird. Das verwendet den Index.

Wenn Sie points.in (1,2,3) hinzufügen, gibt das 3 Ergebnisse zurück und jedes muss der Bereichstabelle zugeordnet werden, daher funktioniert es nicht

Ergebnis

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   

Sie können Ihren Test ohne die Punktetabelle vereinfachen, indem Sie Folgendes tun: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

Und jetzt das; SELECT * FROM ranges where mbrcontains( poly, GEOMFROMWKB(POINT(0, 0))) OR mbrcontains( poly, GEOMFROMWKB(POINT(10, 10)))

Ergebnis

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

Beachten Sie, dass Sie im zweiten Fall keinen Index verwenden und nur scannen.

Sie könnten die Abfrage zwingen, den Index zu verwenden, indem Sie UNION für jeden bestimmten Punkt erstellen, aber ich bin mir nicht sicher, ob das schneller sein wird. Ich habe einige Tests lokal durchgeführt und es war etwas langsamer als Ihre erste Abfrage.

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

Ergebnis

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