PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Reutilizar valor de seleção calculado

Tempo de teste


Você não vê a avaliação de funções individuais por linha no EXPLAIN resultado.

Teste com EXPLAIN ANALYZE para obter tempos de consulta reais para comparar a eficácia geral. Execute algumas vezes para descartar artefatos de armazenamento em cache. Para consultas simples como essa, você obtém números mais confiáveis ​​para o tempo de execução total com:
EXPLAIN (ANALYZE, TIMING OFF) SELECT ...

Requer Postgres 9.2+ . Por documentação :

Evitar avaliações repetidas


Normalmente, as expressões em uma subconsulta são avaliadas uma vez . Mas o Postgres pode recolher subconsultas triviais se achar que isso será mais rápido.

Para introduzir uma barreira de otimização, você pode usar um CTE em vez da subconsulta. Isso garantia que o Postgres calcula ST_SnapToGrid(geom, 50) apenas uma vez:
WITH cte AS (
   SELECT ST_SnapToGrid(geom, 50) AS geom1
   FROM   points
   )
SELECT COUNT(*)   AS n
     , ST_X(geom1) AS x
     , ST_Y(geom1) AS y
FROM   cte
GROUP  BY geom1;         -- see below

No entanto, isso é provavelmente mais lento do que uma subconsulta devido a mais sobrecarga para um CTE. A chamada de função é provavelmente muito barata. Geralmente, o Postgres sabe melhor como otimizar um plano de consulta. Só introduza essa barreira de otimização se você souber melhor.

Simplifique


Alterei o nome do ponto computado na subconsulta/CTE para geom1 para esclarecer que é diferente do geom original . Isso ajuda a esclarecer o mais importante coisa aqui:
GROUP BY geom1

ao invés de:
GROUP BY x, y

Isso é obviamente mais barato - e pode influenciar se a chamada da função é repetida. Então, isso é provavelmente mais rápido:
SELECT COUNT(*) AS n
     , ST_X(ST_SnapToGrid(geom, 50)) AS x
     , ST_y(ST_SnapToGrid(geom, 50)) AS y
FROM   points
GROUP  BY ST_SnapToGrid(geom, 50);         -- same here!

Ou talvez isso:
SELECT COUNT(*)    AS n
     , ST_X(geom1) AS x
     , ST_y(geom1) AS y
FROM (
   SELECT ST_SnapToGrid(geom, 50) AS geom1
   FROM   points
   ) AS tmp
GROUP  BY geom1;

Teste todos os três com EXPLAIN ANALYZE ou EXPLAIN (ANALYZE, TIMING OFF) e veja por si mesmo. Testando>> adivinhando.