sql >> Database >  >> RDS >> Mysql

Ruimtelijke index wordt niet gebruikt

Helaas ST_Distance() < threshold is geen sargable zoekcriterium. Om aan deze query te voldoen, moet MySQL de waarde van de functie voor elke rij in de tabel berekenen en deze vervolgens vergelijken met de drempelwaarde. Het moet dus een volledige tabelscan doen (of misschien een volledige indexscan).

Als u een index wilt gebruiken om deze zoekopdracht te versnellen, hebt u een criterium voor een begrenzingsvak nodig. De query is een stuk uitgebreider, maar ook een stuk sneller. Ervan uitgaande dat uw x/y-punten in uw geometrie de lengte- en breedtegraad in graden vertegenwoordigen, kan die zoekopdracht er als volgt uitzien:

   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) 

Hoe werkt dit? Om te beginnen de MbrContains( gebonden,item) functie is sargable . Bovendien levert het grote lelijke concat-item een ​​diagonale lijn op van de zuidwestelijke naar de noordoostelijke hoek van de begrenzende rechthoek. Als je je datapunt en een straal van tien mijl gebruikt, ziet het er zo uit.

LINESTRING(37.8785 -94.2564,38.1684 -93.8884)

Wanneer u de GeomFromText() . gebruikt weergave van die diagonale lijn in het eerste argument naar MbrContains() het dient als een begrenzende rechthoek. MbrContains() kan dan de handige quadtree-geometrie-index gebruiken.

Ten derde, ST_Distance() , in MySQL, verwerkt geen berekeningen voor de breedte- en lengtegraad van grote cirkels. (PostgreSQL heeft een uitgebreidere GIS-extensie .) MySQL's is zo dom als een flapjack in flatland. Het gaat ervan uit dat uw punten in uw geometrische objecten worden weergegeven in vlakke geometrie. Dus ST_Distance() < 10.0 met lng/lat-punten doet iets vreemds.

Er is één fout in de resultaten die deze query genereert; het retourneert alle punten in het selectiekader, niet alleen binnen de opgegeven straal. Dat is op te lossen met een aparte afstandsberekening. Ik heb dit allemaal hier in detail opgeschreven .

Opmerking :Voor breedte- en lengtegraad met GPS-resolutie, 32-bits FLOAT gegevens voldoende nauwkeurig zijn. DOUBLE is wat de geo-extensie van MySQL gebruikt. Als u in graden werkt, ligt meer dan vijf plaatsen achter de komma buiten de nauwkeurigheid van GPS. DECIMAL() is geen ideaal datatype voor lat/lng-coördinaten.




  1. Gegevens importeren uit Excel-spreadsheet of CVS in MySQL

  2. Python:MySQL-verbinding is open, maar kan geen cursor maken

  3. Wat is er aan de hand met Mysql float?

  4. Een back-up maken van een PostgreSQL-database en deze herstellen via DBeaver