sql >> Base de Datos >  >> RDS >> Mysql

Índice espacial no utilizado

Desafortunadamente ST_Distance() < threshold no es un sargable criterio de búsqueda. Para satisfacer esta consulta, MySQL debe calcular el valor de la función para cada fila de la tabla y luego compararlo con el umbral. Por lo tanto, tiene que hacer un escaneo de tabla completo (o tal vez un escaneo de índice completo).

Para explotar un índice para acelerar esta consulta, necesitará un criterio de cuadro delimitador. La consulta es mucho más elaborada pero también mucho más rápida. Suponiendo que sus puntos x/y en su geometría representen latitud/longitud en grados, esa consulta podría verse así:

   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) 

¿Como funciona esto? Por un lado, MbrContains( encuadernado, elemento) función es sargable . Por otro lado, el elemento grande y feo de concat produce una línea diagonal desde el suroeste hasta la esquina noreste del rectángulo delimitador. Usando su punto de datos y un radio de diez millas, se ve así.

LINESTRING(37.8785 -94.2564,38.1684 -93.8884)

Cuando usa el GeomFromText() representación de esa línea diagonal en el primer argumento de MbrContains() sirve como un rectángulo delimitador. MbrContains() luego puede explotar el ingenioso índice de geometría quadtree.

En tercer lugar, ST_Distance() , en MySQL, no maneja los cálculos de latitud y longitud del gran círculo. (PostgreSQL tiene una extensión GIS más completa .) MySQL es tan tonto como un flapjack en flatland. Asume que sus puntos en sus objetos geométricos están representados en geometría plana. Entonces ST_Distance() < 10.0 con puntos lng/lat hace algo extraño.

Hay un defecto en los resultados que genera esta consulta; devuelve todos los puntos en el cuadro delimitador, no solo dentro del radio especificado. Eso se puede resolver con un cálculo de distancia separado. He escrito todo esto con cierto detalle aquí .

Nota :para latitud y longitud con resolución GPS, FLOAT de 32 bits Los datos tienen suficiente precisión. DOUBLE es lo que usa la extensión geográfica de MySQL. Cuando está trabajando en grados, más de cinco lugares después del punto decimal está más allá de la precisión del GPS. DECIMAL() no es un tipo de datos ideal para coordenadas lat/lng.