Eu tenho uma tabela do PostgreSQL 9.1 com centenas de milhares de pontos do PostGIS. Para cada uma dessas opções, eu gostaria de encontrar o ponto mais próximo em outra tabela de PONTOS. Os pontos da segunda tabela representam uma grade em todo o mundo, então eu sei que sempre haverá uma correspondência dentro de 1 grau. Esta é a consulta que estou usando até agora, que faz uso de índices GIST, por isso é razoavelmente rápido (cerca de 30 segundos no 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)
O único problema é a linha de dados. Os pontos da grade têm apenas latitude 180, não -180. Ao usar a versão geométrica de ST_Distance, isso não retorna pontos do outro lado da linha de dados. Por exemplo. se p.pos for POINT(-179.88056 -16.68833)
o ponto de grade mais próximo POINT(180 -16.25)
, mas a consulta acima não o retornará. Qual é a melhor maneira de corrigir isso?
Eu realmente não quero ter duas coordenadas para um único ponto de grade (-180 e +180). Tentei adicionar minha própria função que verifica esse caso específico, mas a consulta não retorna em 5 minutos, provavelmente porque não pode mais usar o índice. Eu também tentei usar a versão geográfica do ST_DWithin e essa consulta também não retornou após 5 minutos.
Respostas:
OK, finalmente descobri uma maneira de hackear isso, que não apenas contorna o problema da linha de dados, mas também é mais rápido.
Fiquei muito surpreso ao ver que essa função, que é chamada para todas as linhas, é mais rápida que a função original da janela, mas é - mais de 10 vezes mais rápida. O desempenho do PostgreSQL é realmente uma arte negra!
fonte