J'essaie de comprendre l'impact sur les performances de la sélection de données dans une vue, où l'une des colonnes d'une vue est fonction d'autres données de la table d'origine.
Le calcul est-il effectué indépendamment du fait que la colonne calculée figure ou non dans la liste des colonnes sélectionnées?
Si j'avais une table et la vue déclarée comme ça
CREATE TABLE price_data (
ticker text, -- Ticker of the stock
ddate date, -- Date for this price
price float8, -- Closing price on this date
factor float8 -- Factor to convert this price to USD
);
CREATE VIEW prices AS
SELECT ticker,
ddate,
price,
factor,
price * factor as price_usd
FROM price_data
Would que la multiplication être effectuée dans une requête comme celle ci - dessous?
select ticker, ddate, price, factor from prices
Existe-t-il une référence garantissant ceci dans un sens ou dans l'autre? Je lisais la documentation sur le système de règles dans Postgres, mais je pense que la réponse réside vraiment dans l'optimiseur, car rien dans la documentation du système de règles n'indiquait qu'il ne serait pas sélectionné.
Je soupçonne que dans le cas ci-dessus, le calcul n'est pas effectué. J'ai changé la vue pour utiliser la division au lieu de la multiplication et j'ai inséré un 0
for factor
dans price_data
. La requête ci-dessus n'a pas échoué, mais si la requête a été modifiée pour sélectionner la colonne calculée, la requête modifiée a échoué.
Existe-t-il un moyen de comprendre quels calculs sont effectués lors de l' select
exécution d'un? Je suppose que je suis à la recherche de quelque chose comme, EXPLAIN
mais qui me renseigne également sur les calculs qui sont effectués.
la source
Réponses:
Comme l'a dit @Laurenz, votre analyse est correcte: l'optimiseur évitera d'évaluer les expressions de colonne qui n'affectent pas le résultat de la requête (et votre tentative de forcer une erreur de division par zéro en est la preuve).
Cela dépend des colonnes que vous sélectionnez, mais cela dépend également de la catégorie de volatilité des expressions de colonne. L'optimiseur est libre d'omettre
immutable
et d'stable
appeler des fonctions si leur sortie n'est jamais utilisée, car elles ne peuvent pas affecter le résultat, mais lesvolatile
fonctions peuvent avoir des effets secondaires, de sorte qu'elles ne sont pas si facilement optimisées.Par exemple:
Si seule la
volatile
colonne est sélectionnée:... alors comme vous pouvez le voir,
stable_function()
est absent de laexplain
sortie, et l'absence d'unNOTICE
confirme que cet appel a été optimisé loin.Cependant, si la
stable
colonne est sélectionnée à la place:... alors nous voyons les deux expressions de colonne apparaître dans le plan, et les
NOTICE
s montrent que les deux fonctions ont été exécutées.Il ne semble pas y avoir de mention explicite de ce comportement dans les documents, il n'y a donc aucune garantie ferme quant à l'évaluation ou non d'une expression, et vous ne devriez pas vous fier aux effets secondaires que vos appels de fonction pourraient avoir.
Mais si votre seule préoccupation est la performance, tant que vous marquez vos fonctions comme
stable
ou leimmutable
cas échéant, vous pouvez être raisonnablement sûr (en particulier dans des cas simples comme celui-ci) qu'elles ne seront évaluées que si elles sont nécessaires.(Et pendant que vous êtes là pour auditer vos déclarations de volatilité, vous pouvez également définir les indicateurs de sécurité parallèles .)
la source
Votre suspicion est correcte et le calcul ne doit pas être effectué si la colonne n'est pas utilisée.
Pour confirmer cela, regardez la sortie de
EXPLAIN (VERBOSE)
pour la requête, qui vous montrera les colonnes retournées.la source