Consultas retornando conjuntos de dados muito grandes no PostGIS

8

Eu tenho uma consulta PostGIS que retornará vários milhões de linhas:

SELECT 
 t1.id AS id1,
 t2.id AS id2,
 ABS(t1.mean_h - t2.mean_h) AS h_diff, 
 ST_Distance(t1.the_geom, t2.the_geom) AS dist  
FROM tas_ponds as t1, tas_ponds as t2 
WHERE
 (t1.gid > t2.gid) AND
 ST_DWithin(t1.the_geom, t2.the_geom, 17000)

Quando executado psql, recebo um out of memory for query resulterro.

O Google sugere que isso seja um erro no psql, em vez de no postgres / PostGIS. Alterar a consulta no formulário SELECT ... INTO x FROM ...resolveria o problema? Existem outras abordagens recomendadas para lidar com conjuntos de dados muito grandes?

fmark
fonte

Respostas:

7

Alguns bisbilhoteiros confirmam que este é um problema do cliente do Postgres, independente de considerações espaciais ou do servidor: o cliente possui uma quantidade limitada de memória para armazenar em buffer os resultados antes de exibi-los na tela, o que você está excedendo.

A abordagem recomendada para lidar com isso é usar uma abordagem DECLARE / FETCH para acessar os dados em blocos menores que o conjunto total de resultados. Você também pode criar uma exibição com componentes da consulta (por exemplo, distância) para reduzir a memória necessária para a operação da consulta.

scw
fonte
5

O scw me pegou por dois minutos, então não vou repetir sua resposta. Aqui estão algumas outras soluções possíveis:

  • Edite a Memoryseção de postgresql.conf. Tente verificar se você possui configurações de memória extremamente baixas que podem impedir a execução da consulta.

  • Tente gravar a consulta em um arquivo e execute a partir da linha de comando, usando:

    psql -f nome do arquivo db_name> output_file

  • Se você pretende usar os resultados em um aplicativo externo, tente Executar a consulta usando um cursor externo psql. Por exemplo, um script Python que executaria sua consulta:

roteiro:

try:
    conn = psycopg2.connect("dbname='' user='' host='' password=''") # Fill in
    cur = conn.cursor()
except:
        print 'Unable to connect to the database'
else:
        print 'Connected to database.'

query="""YOUR
         QUERY
         HERE"""
cur.execute(query)

Um cursor é iterável, então você pode:

for result in cur:
    print result

Ou obtenha todos:

 results=cur.fetchall()
Adam Matan
fonte
2
Eu posso estar errado, mas não acho que as primeiras (e talvez a segunda) soluções funcionem. O primeiro modifica a memória do servidor, e esse é um problema do cliente, não relacionado à memória disponível no DMBS, e o segundo provavelmente sofreria o mesmo problema, a menos que apenas o buffer da tela seja o problema. Sua terceira solução é melhor que a minha IMO, pois oferece controle refinado em um ambiente flexível com o cursor, o que é um pouco mais complicado em SQL bruto. +1
scw 12/08/10
@ SCW Você provavelmente está certo sobre a primeira (e talvez a segunda) solução. O problema é que, às vezes, esses truques específicos parecem funcionar com o PostgreSQL, eles podem melhorar o desempenho geral e levam pouco tempo e esforço para serem testados. Aprendi muito com sua resposta.
Adam Matan
2

Para o registro, no meu caso, armazenar o conjunto de dados retornado em outra tabela usando a SELECT ... INTO ...sintaxe trabalhada.

Ele não apenas resolveu o problema de falta de memória, mas também foi substancialmente mais rápido que a consulta original.

fmark
fonte
1

A indexação é muito importante no Postgres e PostGIS

http://postgis.refractions.net/docs/ch04.html#id2794434

Recomende índices GiST (Árvores de Pesquisa Generalizada) para conjuntos de dados muito grandes .... (também é "nulo seguro") exemplo CREATE INDEX [indexname] ON [tablename] USING GIST ([geometryfield]);

Após criar um índice, é importante forçar o PostgreSQL a coletar estatísticas da tabela, que são usadas para otimizar os planos de consulta

ANÁLISE DE VÁCUO [nome_tabela] [nome_coluna]; SELECT UPDATE_GEOMETRY_STATS ([table_name], [column_name]);

Também é uma boa referência: Aproveitando os índices http://postgis.refractions.net/docs/ch04.html#id2794685

Mapperz
fonte
Sim, indexei e aspirei as tabelas e confirmei que meus índices estão sendo usados ​​via EXPLAIN etc. No entanto, meu problema não é com velocidade (neste momento), mas com um erro de falta de memória.
fmark 12/08