No puedo ejecutar PostGIS 2.1 en PostgreSQL 9.3.5 para usar un índice espacial incluso para las consultas más simples. El conjunto de datos completo es de 8 millones de puntos (cuadrícula de conteo de población desde aquí) . La tabla se crea como
CREATE TABLE points (
population DOUBLE PRECISION NOT NULL,
location GEOGRAPHY(4326, POINT) NOT NULL
)
CREATE INDEX points_gix ON points USING GIST(location);
Las consultas son tan simples como se obtienen
SELECT SUM(population)
FROM points
WHERE ST_Distance(
location,
ST_GeographyFromText('SRID=4326; POINT(0 0)')
) < 1000
PostgreSQL siempre usa el escaneo Seq para ello, he intentado un subconjunto con 10000 puntos, todavía escaneo Seq. ¿Algunas ideas?
Respuestas:
ST_Distance en realidad calcula la distancia entre todos los pares de puntos, por lo que, como tal, no se puede usar ningún índice. Por lo tanto, su consulta realizará un escaneo de secuencia y luego elegirá aquellas geometrías que sean inferiores a la distancia que especifique. Está buscando ST_DWithin , que usa un índice.
ST_Distance es más útil para ordenar resultados, a menudo junto con ORDER BY y / o LIMIT, que se han obtenido con consultas que sí usan un índice.
fuente
Como dijo @ JohnPowellakaBarça,
ST_DWithin()
es el camino a seguir cuando se desea corrección .Sin embargo, en mi caso solo quiero una estimación aproximada, por lo que incluso
ST_DWithin()
era demasiado costoso (en costo de consulta) para mis necesidades. Usé&&
yST_Expand(box2d)
(no confundas esto con lageometry
versión) en su lugar. Ejemplo:Lo que será inmediatamente obvio es que estamos tratando con grados en lugar de metros, y usando un cuadro delimitador en lugar de un círculo en un esferoide. Para mi caso de uso, esto reduce de 24 ms a solo 2 ms (localmente en SSD). Sin embargo, para mi base de datos de producción en AWS RDS PostgreSQL con conexiones concurrentes y cuotas IOPS poco generosas (100 IOPS), la
ST_DWithin()
consulta original gasta demasiado IOPS y puede ejecutarse más de 2000 ms y mucho peor cuando la cuota IOPS se agota.Esto no es para todos, pero en caso de que pueda sacrificar algo de precisión por la velocidad (o para guardar IOPS), entonces este enfoque puede ser para usted. Como puede ver en los planes de consulta a continuación,
ST_DWithin
todavía requiere un filtro espacial dentro de la exploración de montón de mapa de bits además de Recheck Cond, mientras que&&
en una caja la geometría no necesita un filtro y solo usa Recheck Cond.También noté que eso
IS NOT NULL
importa, sin él te quedarás con un plan de consulta peor. Parece que el índice GIST no es "lo suficientemente inteligente" para esto. (por supuesto, no es necesario si su columna esNOT NULL
, en mi caso esNULL
capaz)Tabla de 20000 filas,
ST_DWithin(geography, geography, 100000, FALSE)
en AWS RDS 512 MB RAM con 300 IOPS:Tabla de 20000 filas
&&
yST_Expand(box2d)
en AWS RDS 512 MB RAM con 300 IOPS:De nuevo con una consulta más simple:
Tabla de 20000 filas,
ST_DWithin(geography, geography, 100000, FALSE)
en AWS RDS 512 MB RAM con 300 IOPS:Tabla de 20000 filas
&&
yST_Expand(box2d)
en AWS RDS 512 MB RAM con 300 IOPS:fuente