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

Indeks przestrzenny nie jest używany

Niestety ST_Distance() < threshold nie jest szargable kryterium wyszukiwania. Aby spełnić to zapytanie, MySQL musi obliczyć wartość funkcji dla każdego wiersza w tabeli, a następnie porównać ją z progiem. Musi więc wykonać pełne skanowanie tabeli (lub może pełne skanowanie indeksu).

Aby wykorzystać indeks do przyspieszenia tego zapytania, będziesz potrzebować kryterium ograniczającego. Zapytanie jest dużo bardziej rozbudowane, ale także dużo szybsze. Zakładając, że punkty x/y w geometrii reprezentują szerokość/długość geograficzną w stopniach, zapytanie to może wyglądać tak:

   set @latpoint = 38.0234332;
   set @lngpoint = -94.0724223;
   set @r = 10.0;    /* ten mile radius */
   set @units=69.0;    /* 69 statute miles per degree */
   SELECT AsText(geo) 
     FROM markers
      WHERE MbrContains(GeomFromText( 
       CONCAT('LINESTRING(', @latpoint-(@r/@units),' ',
                             @lngpoint-(@r /(@units* COS(RADIANS(@latpoint)))), 
                          ',', 
                             @latpoint+(@r/@units) ,' ', 
                             @lngpoint+(@r /(@units * COS(RADIANS(@latpoint)))),
                           ')')),
                    geo) 

Jak to działa? Po pierwsze, MbrContains( związany, przedmiot) funkcja jest sargable . Po drugie, duży brzydki element concat tworzy ukośną linię od południowego zachodu do północno-wschodniego narożnika prostokąta ograniczającego. Przy użyciu punktu danych i promienia dziesięciu mil wygląda to tak.

LINESTRING(37.8785 -94.2564,38.1684 -93.8884)

Kiedy używasz GeomFromText() renderowanie tej ukośnej linii w pierwszym argumencie MbrContains() służy jako prostokąt graniczny. MbrContains() może następnie wykorzystać sprytny indeks geometrii drzewa czworokątnego.

Po trzecie, ST_Distance() , w MySQL, nie obsługuje obliczeń szerokości i długości geograficznej po wielkim okręgu. (PostgreSQL ma bardziej wszechstronne rozszerzenie GIS .) MySQL jest tak głupi jak klapa w flatland. Zakłada, że ​​twoje punkty w twoich obiektach geometrycznych są reprezentowane w geometrii płaskiej. Więc ST_Distance() < 10.0 z punktami lng/lat robi coś dziwnego.

Jest jeden błąd w wynikach generowanych przez to zapytanie; zwraca wszystkie punkty w obwiedni, a nie tylko w określonym promieniu. Można to rozwiązać za pomocą oddzielnego obliczenia odległości. Opisałem to wszystko szczegółowo tutaj .

Uwaga :Dla szerokości i długości geograficznej w rozdzielczości GPS, 32-bitowy FLOAT dane mają wystarczającą precyzję. DOUBLE jest to, czego używa rozszerzenie geograficzne MySQL. Kiedy pracujesz w stopniach, więcej niż pięć miejsc po przecinku przekracza dokładność GPS. DECIMAL() nie jest idealnym typem danych dla współrzędnych lat/lng.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. tabela sql z kluczem podstawowym z innej tabeli

  2. formularz przepustki wybrany do następnej strony

  3. ustaw wartość początkową automatycznej inkrementacji dla tabeli mysql

  4. Uwagi dotyczące wydajności PDO fetchall()?

  5. WSTAW z WYBIERZ