PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Réutiliser la valeur de sélection calculée

Temps de test

Vous ne voyez pas l'évaluation des fonctions individuelles par ligne dans le EXPLAIN production.

Testez avec EXPLAIN ANALYZE pour obtenir des temps de requête réels afin de comparer l'efficacité globale. Exécutez plusieurs fois pour exclure les artefacts de mise en cache. Pour des requêtes simples comme celle-ci, vous obtenez des chiffres plus fiables pour le temps d'exécution total avec :

EXPLAIN (ANALYZE, TIMING OFF) SELECT ...

Nécessite Postgres 9.2+ . Par documentation :

Éviter les évaluations répétées

Normalement, les expressions d'une sous-requête sont évaluées une fois . Mais Postgres peut réduire les sous-requêtes triviales s'il pense que ce sera plus rapide.

Pour introduire une barrière d'optimisation, vous pouvez utiliser un CTE au lieu de la sous-requête. Cela garantit que Postgres calcule ST_SnapToGrid(geom, 50) une seule fois :

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

Cependant, c'est probablement plus lent qu'une sous-requête en raison de plus de temps système pour un CTE. L'appel de fonction est probablement très bon marché. Généralement, Postgres sait mieux comment optimiser un plan de requête. N'introduisez une telle barrière d'optimisation que si vous en savez plus.

Simplifier

J'ai changé le nom du point calculé dans la sous-requête / CTE en geom1 pour clarifier, c'est différent de l'original geom . Cela aide à clarifier le plus important chose ici :

GROUP BY geom1

au lieu de :

GROUP BY x, y

C'est évidemment moins cher - et peut avoir une influence sur la répétition de l'appel de fonction. Donc, c'est probablement le plus rapide :

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 peut-être ceci :

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;

Testez les trois avec EXPLAIN ANALYZE ou EXPLAIN (ANALYZE, TIMING OFF) et voyez par vous-même. Tester>> deviner.