Existe uma função dissolver no PostGIS diferente de st_union?

22

Estou procurando uma função para dissolver limites compartilhados entre recursos de polígono em uma tabela. ST_UNION () quase faz o que estou procurando, mas cria um multipolígono a partir de todos os polígonos da camada, independentemente de compartilharem ou não um limite comum. Prefiro apenas dissolver limites entre polígonos que se tocam. Imaginei que deveria haver alguma maneira de usar ST_TOUCHES (), mas a necessidade de uma função dissolver parece tão comum que ficaria surpreso se não houvesse uma função interna para conseguir isso.

O caso de uso é o seguinte: baixei os dados do Corine Landcover para um grande país europeu e quero dissolver os limites entre os diferentes tipos de floresta (aproximadamente 75.000 polígonos em uma tabela). Eu tentei ST_UNION, mas ele me falha com um erro de "falta de memória" (30.000 polígonos funcionaram):

create table corine00 as 
  select st_union(the_geom) as the_geom, 
         sum(area_ha) as area_ha,
         substr(code_00,1,2) as code_00
  from clc00_c31_forests
  group by substr(code_00,1,2)

Nota: Todos os códigos de floresta começam com '31' e estou usando o PostGIS 1.4, versão GEOS: 3.2.0-CAPI-1.6.0

underdark
fonte

Respostas:

21

ST_MemUnion () executará um processo amigável de memória ingênua e lenta. Você pode tentar que, se o seu problema for pequeno o suficiente, ele poderá ser concluído em um período de tempo razoável. Você também pode dividir o problema em duas partes e, em seguida, executá-las juntas. Como os resultantes terão muito menos pontos do que as entradas, você poderá ajustar todo o problema na memória dessa maneira. Ou use a rotina de fome rápida de memória nas metades e a rotina mais lenta na mesclagem final.

Paul Ramsey
fonte
4
Fantástico tê-lo aqui, Paul, obrigado por lhe trazer uma experiência incomparável.
fmark
1
Obrigado, parece que meu problema não é pequeno o suficiente. ST_MemUnion () está em execução há 24 horas. Vou tentar dividir o problema.
Underdark
5

Acredito que ST_Dump é o que você deseja:

ST_Dump :

Retorna um conjunto de linhas geometry_dump (geom, path), que compõem uma geometria g1 .... Por exemplo, ele pode ser usado para expandir MULTIPOLYGONS em POLYGONS. ...

Então, para o seu caso:

 SELECT (ST_Dump( ST_Union( the_geom ) )).geom
 FROM clc00_c31_forests
 GROUP BY substr(code_00,1,2)

Não tenho certeza de como ele irá interagir com a criação da tabela que você está tentando fazer, mas deve fornecer as geometrias como entradas separadas. Você seria capaz de fazer uma junção espacial (usando && e ST_Contains) entre as duas tabelas para coletar os dados nas geometrias.

yhw42
fonte
2
Nota: isso só será útil se você resolver os problemas de memória do ST_Union! :)
yhw42
4

Seu PostGIS é compilado com o GEOS 3.1.0+? Para essa versão, uma união em cascata muito mais rápida foi implementada, mas se não for encontrada, usará o código mais antigo, que é de ordem de magnitude mais lenta.

Atualização : parece que seu PostGIS está usando a abordagem de união em cascata, mas a falta de memória é real. Eu tentaria aumentar a memória disponível para sua instância do Postgres, eis alguns conselhos da palestra de Paul Ramsey em 2007 sobre o FOSS4G PostGIS :

  • O acesso ao disco é lento, portanto, é possível obter maior desempenho usando mais memória para armazenar dados em cache!
    • Aumentar shared_buffers
    • RAM física - necessidades do sistema operacional * 75%
  • A classificação é mais rápida na memória
    • Aumentar work_mem
  • A limpeza do disco é mais rápida com mais memória
    • Aumentar maintenance_work_mem
  • Alocado por conexão
  • Além disso
    • Aumentar wal_buffers
    • Aumentar checkpoint_segments
    • Diminuir random_page_cost

No seu caso, eu tentaria aumentar shared_buffers, a recomendação geral é de 25% da memória disponível para um servidor de banco de dados, mas tente aumentá-lo para 3-4x seu valor atual e ver se ele é concluído.

scw
fonte
postgis_geos_version () retorna: 3.2.0-CAPI-1.6.0 ... Acho que está bem. Tentará ST_Collect, obrigado.
Underdark
Bem, ST_Collect parece não dissolver nenhum limite e também cria um Multipolígono gigante.
underdark
Sim, eu li mal a página para ST_Collect. Atualizei minha resposta para fornecer conselhos mais específicos para ajustar o uso de memória do Postgres.
ACS