sql >> Databáze >  >> RDS >> Mysql

Připojuje se k prostorovým mysql indexům

Věřím, že je to proto, že MySQL nepodporuje slučování prostorových indexů. Nejsem si jistý, jestli je to stále pravda, ale někde jsem to v minulosti četl. Pokud máte příkaz OR, pak se prostorové indexy nepoužívají

Ve vašem případě, kde děláte points.id =1, je to přímý výběr s jedním vráceným výsledkem, který se použije v mbrcontains. To používá index.

Když přidáte points.in (1,2,3), vrátí to 3 výsledky a každý musí být namapován do tabulky rozsahů, proto nefunguje

výsledek

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   

Svůj test bez tabulky bodů můžete zjednodušit takto:SELECT * FROM rozsahy, kde 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

A teď tohle; SELECT * FROM rozsahy, kde mbrcontains( poly, GEOMFROMWKB(POINT(0, 0))) NEBO mbrcontains( poly, GEOMFROMWKB(POINT(10, 10)))

výsledek

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

Podívejte se, že ve druhém případě nepoužíváte index a pouze skenujete.

Můžete donutit dotaz použít index vytvořením UNION pro každý konkrétní bod, ale nejsem si jistý, zda to bude rychlejší. Provedl jsem nějaké testy lokálně a bylo to trochu pomalejší než váš první dotaz.

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

výsledek

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. Správný způsob použití kopie Postgres jdbc

  2. Tomcat 6/7 JNDI s více zdroji dat

  3. Duplicitní záznamy v DB

  4. JpaSpecificationExecutor JOIN + ORDER BY ve specifikaci