Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Sprzężenia na przestrzennych indeksach mysql

Uważam, że dzieje się tak dlatego, że MySQL nie obsługuje scalania indeksów przestrzennych. Nie jestem pewien, czy to nadal prawda, ale czytałem to gdzieś w przeszłości. Jeśli masz instrukcję OR, indeksy przestrzenne nie są używane

W twoim przypadku, gdzie robisz points.id =1, jest to prosty wybór z jednym zwróconym wynikiem, który jest używany w mbrcontains. Używa indeksu.

Po dodaniu points.in (1,2,3) zwraca 3 wyniki, a każdy z nich musi być zmapowany do tabeli zakresów, dlatego nie działa

wynik

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   

Możesz uprościć test bez tabeli punktów, wykonując następujące czynności:SELECT * FROM zakresy, w których 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 teraz to; SELECT * FROM zakresy, w których mbrcontains( poly, GEOMFROMWKB(POINT(0, 0))) OR mbrcontains( poly, GEOMFROMWKB(POINT(10, 10))))

wynik

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

Zobacz, że w drugim przypadku nie używasz indeksu i po prostu skanujesz.

Możesz zmusić zapytanie do użycia indeksu, tworząc UNION dla każdego określonego punktu, ale nie jestem pewien, czy to będzie szybsze. Zrobiłem kilka testów lokalnie i było to trochę wolniejsze niż twoje pierwsze zapytanie.

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

wynik

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. JDBC podaje datę i godzinę MySQL w UTC

  2. Jakie jest najlepsze kodowanie znaków dla języka japońskiego dla wyświetlania DB, php i html?

  3. Jak mogę wyszukiwać w tabeli wartości oddzielonych przecinkami?

  4. Czy mogę używać obiektów Django F() z konkatenacją ciągów?

  5. kod php do testowania pdo jest dostępny?