Question débutant:
J'ai une fonction coûteuse f(x, y)
sur deux colonnes x et y dans ma table de base de données.
Je veux exécuter une requête qui me donne le résultat de la fonction en tant que colonne et y met une contrainte, quelque chose comme
SELECT *, f(x, y) AS func FROM table_name WHERE func < 10;
Mais cela ne fonctionne pas, je vais donc devoir écrire quelque chose comme
SELECT *, f(x, y) AS func FROM table_name WHERE f(x, y) < 10;
Est-ce que cela exécutera la fonction coûteuse deux fois? Quelle est la meilleure façon de procéder?
postgresql
postgresql-9.4
Jack Black
la source
la source
STABLE
/IMMUTABLE
ouVOLATILE
?Réponses:
Créons une fonction qui a un effet secondaire afin que nous puissions voir combien de fois elle est exécutée:
Et puis appelez cela comme vous le faites:
Comme vous le voyez, la fonction est appelée au moins une fois (à partir de la
WHERE
clause), et lorsque la condition est vraie, une fois de plus pour produire la sortie.Pour éviter la deuxième exécution, vous pouvez faire ce que suggère Edgar - à savoir envelopper la requête et filtrer l'ensemble de résultats:
Pour vérifier plus en détail comment cela fonctionne, on peut y aller
pg_stat_user_functions
et vérifiercalls
(étant donnétrack_functions
est réglé sur «tous»).Essayons avec quelque chose qui n'a aucun effet secondaire:
simple()
est en fait trop simple pour pouvoir être inséré , il n'apparaît donc pas dans la vue. Rendons-le non-inlinable:En apparence, l'image est la même avec ou sans effets secondaires.
Changer
other_one()
pourIMMUTABLE
changer le comportement (peut-être surprenant) au pire, car il sera appelé 13 fois dans les deux requêtes.la source
Essayez de l'appeler à nouveau:
la source