Mysql
 sql >> база данни >  >> RDS >> Mysql

Присъединява се към пространствени mysql индекси

Вярвам, че това е така, защото MySQL не поддържа обединяване на пространствени индекси. Не съм сигурен дали все още е вярно, но съм го чел някъде в миналото. Ако имате оператор ИЛИ, тогава пространствените индекси не се използват

Във вашия случай къде правите points.id =1, това е директно избиране с един върнат резултат, който се използва в mbrcontains. Това използва индекса.

Когато добавите points.in (1,2,3), това връща 3 резултата и всеки трябва да бъде съпоставен към таблицата с диапазони, следователно не работи

резултат

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   

Можете да опростите теста си без таблицата с точки, като направите следното:SELECT * FROM диапазони, където 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

А сега това; ИЗБЕРЕТЕ * ОТ диапазони, където mbrсъдържа(поли, GEOMFROMWKB(ТОЧКА(0, 0))) ИЛИ mbrсъдържа(поли, GEOMFROMWKB(ТОЧКА(10, 10)))

резултат

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

Вижте, че във втория случай не използвате индекс, а просто сканирате.

Можете да принудите заявката да използва индекс, като създадете UNION за всяка конкретна точка, но не съм сигурен дали това ще бъде по-бързо. Направих някои тестове на място и беше малко по-бавно от първото ви запитване.

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

резултат

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Въпрос за дизайн на база данни

  2. Apache Solr java уроци

  3. Вмъкване на MySQL променливи в Google карти с PHP

  4. ГРЕШКА 1045 (28000):Достъпът е отказан за потребител 'root'@'localhost' (използвайки парола:НЕ)

  5. Как да проверя дали MySQL таблицата е UTF-8 и има storageEngine InnoDB?