sql >> Database >  >> RDS >> Mysql

Doet mee aan ruimtelijke mysql-indexen

Ik geloof dat dit komt omdat MySQL geen ondersteuning biedt voor het samenvoegen van ruimtelijke indexen. Ik weet niet zeker of het nog steeds waar is, maar ik heb het ergens in het verleden gelezen. Als je een OR-statement hebt, worden de ruimtelijke indexen niet gebruikt

In jouw geval, waar doe je points.id =1, dat is een rechte selectie met één geretourneerd resultaat dat wordt gebruikt in de mbrcontains. Dat maakt gebruik van de index.

Wanneer u points.in (1,2,3) toevoegt, levert dat 3 resultaten op en elk moet worden toegewezen aan de bereiktabel, en werkt daarom niet

resultaat

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   

U kunt uw test vereenvoudigen zonder de puntentabel door dit te doen:SELECT * FROM bereiken waar mbrbevat( 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

En nu dit; SELECTEER * FROM bereiken waar mbrbevat( poly, GEOMFROMWKB(POINT(0, 0))) OF mbrbevat( poly, GEOMFROMWKB(POINT(10, 10)))

resultaat

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

Zie dat in het tweede geval u geen index gebruikt en alleen scant.

Je zou de query kunnen dwingen om index te gebruiken door UNION te maken voor elk specifiek punt, maar ik weet niet zeker of dat sneller zal zijn. Ik heb wat tests lokaal gedaan en het was iets langzamer dan je eerste vraag.

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

resultaat

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     


  1. Tabel draaien/draaien met aggregatie in Oracle

  2. Hoe de som van de vorige rij van dezelfde kolom op te vragen met pgSql

  3. SQL-opdracht om de taak te stoppen in pgAdmin 4

  4. Controleer en optimaliseer MySQL-database automatisch met Crontab/Cron