Índice espacial PostgreSQL / PostGIS - sem acelerar

15

Eu tenho uma tabela espacial em um banco de dados PostgreSQL / PostGIS. Cada linha nela representa um polígono. É da seguinte forma:

+----+--------+
|gid |   way  |
+----+--------+
|241 | 01030..|

A coluna geométrica é "caminho", que contém a geometria de um polígono. No WKT é: POLYGON (('....')). Estou fazendo muitas consultas ST_Contains nesta tabela, para testar se dois polígonos estão contidos um no outro, por exemplo:

Select ST_Contains(a.way, b.way) From table AS a, table AS b Where a.gid = 15 And b.gid = 16

Eu queria saber como acelerar esta consulta e adicionou um índice espacial na tabela:

CREATE INDEX table_way_gist ON table USING gist(way);

Mas, na verdade, não vejo velocidade. Eu crio o índice APÓS Preencher a tabela com todos os polígonos ANTES de fazer as consultas ST_Contains. O índice deve ser adicionado antes de preencher uma tabela? Existem requisitos especiais na tabela para trabalhar com o índice? A projeção (srid) do caminho da coluna geométrica é definida como 900913.

Estou usando: psql (PostgreSQL) 9.1.4 / POSTGIS = "1.5.3"

MichiMichbeck
fonte

Respostas:

16

O índice mais eficiente para a consulta expressa em sua pergunta é o gid , pois é a única coluna que aparece em uma expressão where:

 CREATE INDEX table_gid ON table (gid);

Você pode soltar com segurança o índice de essência, pois ele consumirá apenas espaço e atrasa as inserções / atualizações / exclusões.

Explicação longa

Como eu disse, o índice mais eficaz no seu caso é o do gid, pois permitirá que o mecanismo db recupere linhas mais rapidamente (com a recuperação geralmente sendo a parte mais lenta do processo). Depois disso, provavelmente calculará melhor o resultado do

  ST_Contains(a.way, b.way)

expressão sem olhar para o índice. A razão é que o planejador de consultas provavelmente estimam que o custo extra de olhar para cima a essência índice em ambas as colunas contra olhando para cima os a.way e b.way valores diretamente não vale a pena o esforço como o número total de linhas de olhar para cima provavelmente é muito pequeno, especialmente se o índice for único.

Como regra geral, lembre-se de que o planejador provavelmente favorecerá uma varredura de tabela em detrimento de uma varredura de índice para conjuntos de dados pequenos (os tamanhos dos conjuntos de dados são estimados observando as estatísticas da tabela).

unicoletti
fonte
Isso deixa a questão mais clara para mim. Eu vou tentar isso. Portanto, se eu colocar a consulta ST_Contains () na cláusula WHERE, o índice espacial deve ser realmente útil? Eu acho que tenho que reorganizar meu script para chamar ST_Contains dentro da cláusula WHERE. No momento, eu estou percorrendo todos os polígonos e sempre teste dois deles separadamente.
MichiMichbeck
?? você está pensando que um índice espacial torna as coisas mais lentas? Essa é nova para mim, porque onde eu trabalho temos índices espaciais para cada mesa única e gostaria de saber se é uma má prática
Luffydude
13

Como disse unicoletti , o índice de essência na coluna geometria só funcionaria se você usar ST_Contains () na expressão WHERE.

Por exemplo, se você gostaria de conhecer todos os polígonos que contêm um ao outro, poderia usar algo como isto:

SELECT a.gid, b.gid
FROM table AS a, table as b
WHERE a.gid != b.gid and ST_Contains(a.way, b.way)

Nesse caso, dependendo do tamanho da sua tabela e da complexidade de suas geometrias, o índice de essência deve fornecer uma velocidade significativa, pois ST_Contains começará a filtrar os polígonos comparando suas caixas de limite antes de realmente verificar suas geometrias completas. Você pode ver uma pequena explicação no Tutorial do OpenGeo .

Alexandre Neto
fonte
Sim, entendo, preciso dessa consulta para envolver o teste de limite de índice. Thx Alexandre. (Eu vou marcar unicoletti como solução, como ele foi rápido e limpou a questão para mim)
MichiMichbeck