Tengo 2 conjuntos de puntos en 2 tablas separadas. La tabla_a tiene 100k puntos y la tabla_b tiene 300k puntos. Intento encontrar los puntos más cercanos en relación a encontrar cualquier punto de la tabla_b que esté a menos de 50 metros de la tabla_a. Después de eso calcular la columna de caída, agruparlos por la columna a_id de la tabla_a y devolver el valor más alto.
Escribí la siguiente consulta que cumple con esta criteira
SELECT DISTINCT ON (a_id) *
FROM (
SELECT
table_b.b_id,
table_b.height - st_3ddistance(table_b.geom, table_a.geom) fall,
table_b.geom,
table_a.a_id
FROM table_a
INNER JOIN table_b ON _st_3ddwithin(table_a.geom, table_b.geom, 50)) a
WHERE fall >= 0
ORDER BY a_id, fall DESC;
He añadido índices de geometría 3d:
CREATE INDEX table_a_geom ON table_a USING GIST (geom gist_geometry_ops_nd);
CREATE INDEX table_b_geom ON table_b USING GIST (geom gist_geometry_ops_nd);
Sin embargo, mi problema es que no puedo hacer una consulta para utilizarlos. El planificador de consultas sigue eligiendo el escaneo de la secuencia que es lento. Hice algunas pruebas cambiando El sistema de la red de distribución de agua es un sistema de distribución de agua que se utiliza para la gestión del agua. con st_3ddwithin , <<->> < 50 creando 50 m de amortiguación e intersección , st_3ddistance < 50 pero cada vez que el planificador está eligiendo la exploración de la secuencia. ¿Hay alguna forma de utilizar índices con mayor rendimiento o de cambiar la consulta para utilizar índices?
Mi plan de consulta:
Unique (cost=10462593.70..10473018.43 rows=1 width=144)
-> Sort (cost=10462593.70..10467806.06 rows=2084945 width=144)
Sort Key: table_a.nmbayuid, ((table_b.height - st_3ddistance(table_b.geomgr, table_a.geom))) DESC
-> Nested Loop (cost=0.00..10243762.28 rows=2084945 width=144)
Join Filter: (_st_dwithin(table_a.geom, table_b.geomgr, '50'::double precision) AND ((table_b.height - st_3ddistance(table_b.geomgr, table_a.geom)) >= '0'::double precision))
-> Seq Scan on e_veg_points_mv12404 table_b (cost=0.00..1459.47 rows=47147 width=96)
-> Materialize (cost=0.00..10.97 rows=398 width=56)
-> Seq Scan on e_wires_mv12404 table_a (cost=0.00..8.98 rows=398 width=56)
1 votos
¿Qué es exactamente e_wires_mv12404 que está en el plan de consulta pero no en el SQL? ¿Qué aspecto tiene el plan de consulta sólo para la consulta interna? Sugiero no utilizar funciones que empiecen por _ST. Por último, es posible que pueda obtener un mejor rendimiento utilizando ST_DWithin en 2D, utilizando 35 metros, que es más o menos lo mismo que 50 metros de los bordes opuestos de un cubo. Como está buscando el punto más cercano en un radio de 50 metros, este podría ser un buen candidato para una unión lateral y utilizar la construcción ORDER BY a.geom <-> b.geom.
1 votos
El año pasado tuve un problema similar, He desenterrado este post para ti Hágame saber si no responde a sus preguntas.
0 votos
@JohnPowellakaBarça, ¿puedes explicar por qué no sugieres funciones que empiecen por "_ST"?
2 votos
Si miras la definición sql de las funciones verás que las funciones st_ como st_dwithin en realidad es una comprobación de cuadro delimitador y una llamada a la función st función. Es la parte del cuadro delimitador la que puede utilizar el índice cuando se llama a la función st no hay forma de que la base de datos utilice el índice. Se llama directamente a la función recheck.
0 votos
@JohnPowellakaBarça He actualizado el plan de consulta eliminando los nombres de tablas extra para evitar despistes. Como me sugeriste he cambiado _st_3ddwithin por st_dwithin y después de VACUUM ANALYZE empieza a funcionar el índice. La última sugerencia es que no estoy buscando el punto más cercano, sino un grupo de puntos en un radio de 50 metros y selecciono el que tenga el valor de sustracción más alto.
1 votos
¿Quieres que escriba la solución de unión lateral, creo que funcionaría bien para lo que describes?
0 votos
@JohnPowellakaBarça si puedes, te lo agradeceré
1 votos
@AndreSilva funciones que empiezan por
_ST
son funciones internas llamadas por PostGIS después de filtrar con un índice. Si las llama directamente, no se utilizará el índice.