Não consigo fazer o PostGIS 2.1 rodar no PostgreSQL 9.3.5 para usar um índice espacial, mesmo para as consultas mais simples. O conjunto de dados inteiro é de 8 milhões de pontos (grade de contagem da população daqui) . A tabela é criada como
CREATE TABLE points (
population DOUBLE PRECISION NOT NULL,
location GEOGRAPHY(4326, POINT) NOT NULL
)
CREATE INDEX points_gix ON points USING GIST(location);
As consultas são tão simples quanto são
SELECT SUM(population)
FROM points
WHERE ST_Distance(
location,
ST_GeographyFromText('SRID=4326; POINT(0 0)')
) < 1000
O PostgreSQL sempre usa a verificação Seq, tentei um subconjunto com 10000 pontos - ainda a verificação Seq. Alguma ideia?
Respostas:
ST_Distance realmente calcula a distância entre todos os pares de pontos, portanto, como tal, nenhum índice poderia ser usado. Portanto, sua consulta fará uma varredura de sequência e escolherá as geometrias inferiores à distância especificada. Você está procurando ST_DWithin , que usa um índice.
ST_Distance é mais útil para solicitar resultados, geralmente em conjunto com ORDER BY e / ou LIMIT, que foram obtidos com consultas que usam um índice.
fonte
Como @ JohnPowellakaBarça disse,
ST_DWithin()
é o caminho a percorrer quando você deseja correção .No entanto, no meu caso, eu quero apenas uma estimativa aproximada, por isso mesmo
ST_DWithin()
era muito caro (no custo da consulta) para minhas necessidades. Eu usei&&
eST_Expand(box2d)
(não confunda isso com ageometry
versão). Exemplo:O que será imediatamente óbvio é que estamos lidando com graus em vez de metros e usando caixa delimitadora em vez de círculo em um esferóide. Para o meu caso de uso, isso reduz de 24 ms para apenas 2 ms (localmente no SSD). No entanto, para meu banco de dados de produção no AWS RDS PostgreSQL com conexões simultâneas e cotas de IOPS pouco generosas (100 IOPS), a
ST_DWithin()
consulta original gasta muito IOPS e pode executar mais de 2000 ms e muito pior quando a cota de IOPS é reduzida.Isso não é para todos, mas, caso você possa sacrificar alguma precisão pela velocidade (ou para salvar IOPS), essa abordagem pode ser sua. Como você pode ver nos planos de consulta abaixo,
ST_DWithin
ainda requer um filtro espacial dentro da verificação de heap de bitmap, além de verificar novamente a Cond, enquanto&&
em uma caixa a geometria não precisa de um filtro e usa apenas a verificação novamente Cond.Também notei que isso
IS NOT NULL
importa, sem ele você ficará com um plano de consulta pior. Parece que o índice GIST não é "inteligente o suficiente" para isso. (é claro que não é necessário se sua coluna forNOT NULL
, no meu caso, éNULL
possível)Tabela de 20.000 linhas,
ST_DWithin(geography, geography, 100000, FALSE)
na AWS RDS 512 MB RAM com 300 IOPS:Tabela de 20000 linhas
&&
eST_Expand(box2d)
na AWS RDS 512 MB RAM com 300 IOPS:Novamente com uma consulta mais simples:
Tabela de 20.000 linhas,
ST_DWithin(geography, geography, 100000, FALSE)
na AWS RDS 512 MB RAM com 300 IOPS:Tabela de 20000 linhas
&&
eST_Expand(box2d)
na AWS RDS 512 MB RAM com 300 IOPS:fonte