Tengo una tabla PostgreSQL 9.1 con cientos de miles de PUNTOS PostGIS. Para cada uno de estos me gustaría encontrar el punto más cercano en otra tabla de PUNTOS. Los puntos en la segunda tabla representan una cuadrícula en todo el mundo, por lo que sé que siempre habrá una coincidencia dentro de 1 grado. Esta es la consulta que estoy usando hasta ahora, que hace uso de índices GIST, por lo que es razonablemente rápido (aproximadamente 30 segundos en total).
SELECT DISTINCT ON (p.id)
p.id, ST_AsText(p.pos)
, ST_AsText(first_value(g.location) OVER (PARTITION BY p.id ORDER BY ST_Distance(p.pos, g.location::geography)))
FROM point p
JOIN grid g ON ST_DWithin(p.pos::geometry, g.location, 1)
El único problema es la fecha. Los puntos de la cuadrícula solo tienen latitud 180, no -180. Cuando se utiliza la versión de geometría de ST_Distance, esto no devuelve puntos en el otro lado de la línea de fecha. P.ej. si p.pos es POINT(-179.88056 -16.68833)
el punto de cuadrícula más cercano POINT(180 -16.25)
, pero la consulta anterior no lo devuelve. ¿Cuál es la mejor manera de arreglar esto?
Realmente no quiero tener dos coordenadas para un solo punto de cuadrícula (-180 y +180). Intenté agregar mi propia función que verifica este caso específico, pero luego la consulta no regresa en 5 minutos, probablemente porque ya no puede usar el índice. También intenté usar la versión de geografía de ST_DWithin y esa consulta tampoco regresó después de 5 minutos.
Respuestas:
OK, finalmente descubrí una manera de hackearlo que no solo funciona alrededor del problema de la fecha, sino que también es más rápido.
Me sorprendió mucho ver que esta función, que se llama para cada fila, es más rápida que la función de ventana original, pero es más de 10 veces más rápida. ¡El rendimiento de PostgreSQL realmente es un arte negro!
fuente