6
votes

Comment réutiliser le résultat pour sélectionner, où et commander par clauses?

La requête suivante retourne les lieux près de nous (Lat: 62.0, Lon: 25.0) À l'intérieur du rayon de laquelle nous tombons en ordre de distance: xxx

est-il possible (et conseillé) de re -Utilisez le résultat de earth_distance (ll_to_earth (62.0, 25.0), ll_to_earth (lat, lon)) au lieu de le calculer séparément pour sélectionner, où et commander par clauses?


2 commentaires

Je pense que si la fonction est marquée comme immuable , le résultat sera réutilisé. Espérons qu'un expert postgres peut me corriger si je me trompe.


@Mikechristensen: Oui, c'est comme ça que ça marche habituellement. Même stable suffit, car cela déclare le résultat constant dans une seule déclaration. immuable est requis pour affirmer des résultats constants, même entre les transactions . Cela est nécessaire pour qu'une fonction soit utilisable dans un index par exemple.


3 Réponses :


3
votes

Lorsque j'utilise principalement MS SQL Server, je suis presque sûr que PostgreSQL prend en charge les CTES. Essayez quelque chose comme: xxx


0 commentaires

0
votes

Vous pouvez également créer une fonction autonome ou emballée et l'utiliser dans vos requêtes:

Select your_function() 
  From your_table...
 Where  ...


2 commentaires

Réponse complètement inutile. 1) La distance calculée doit encore être dans la clause Select, c'est-à-dire que Select * ne fonctionnera pas. 2) L'ensemble de résultats doit toujours être commandé par le résultat de la fonction. 3) Cela équivaut à une requête absolument non différente de celle qui a été publiée à l'origine. La question concerne la volatilité des fonctions et si l'optimiseur de requête évalue la fonction trois fois ou une.


Il suffit d'essayer d'aider ... Veuillez regarder mon exemple à nouveau - les fonctions peuvent être utilisées dans SELECT ... Juste FYI ... et la question portait sur la réutilisation des résultats. La fonction renvoie un résultat et peut être réutilisé ...



4
votes

dans le groupe par et commandez par la clause Vous pouvez vous reporter aux alias de colonne (colonnes de sortie) ou même numéros ordinaux de Sélectionner des éléments . Je cite Le manuel sur commander par :

Chaque expression peut être le nom nom ou numéro ordinal d'une colonne de sortie. (Sélectionnez l'élément de la liste) ou peut être une expression arbitraire formée à partir de Valeurs de colonne d'entrée.

mine d'accompagnement audacieux.

mais dans le et ayant des clauses , vous ne pouvez vous reporter à des colonnes à partir des tables de base (Colonnes d'entrée), vous devez donc épeler votre appel de fonction. xxx

Si vous voulez savoir s'il est plus rapide d'emballer le calcul dans un CTE ou sous-requête, testez-le avec Expliquer analyser . (J'en doute.) xxx

comme @ Mike a commenté , en déclarant une fonction stable (ou immuable ) vous Informez le planificateur de requêtes résultant d'un appel de fonction peut être réutilisé plusieurs fois pour des appels identiques dans une seule déclaration. Je cite Le manuel ici :

Une fonction stable ne peut pas modifier la base de données et est garantie renvoyer les mêmes résultats compte tenu des mêmes arguments pour toutes les lignes dans un déclaration unique. Cette catégorie permet à l'optimiseur d'optimiser Plusieurs appels de la fonction à un seul appel .

Mine d'accompagnement audacieux.


4 commentaires

Très bonne réponse. Juste pour être clair: vous doutez que la sous-requête soit plus rapide que la CTE ou le doute qu'il vaut la peine d'utiliser CTE / SubQuery sur le calculer deux fois deux fois?


@RandomGuy: Je m'attends à ce que la forme simple soit plus rapide qu'avec la sous-requête ou la CTE. Mais juste tester et voir. Tester >> deviner.


@Erwinbrandsetter: Dans mon expérience, CTE est toujours gardé intact, même lorsqu'il est référencé qu'une seule fois (que l'OMI devrait être équivalente à la vue équivalente ou à de (sous-requête) formulaire). En conséquence, ils ne seront pas démontés + réassemblés par le générateur de régimes, que peut conduire à des plans sous-optimaux. Sur le côté plus: cela gardera les plantes relativement petites (et plutôt non liées), ce qui réduira l'explosion combinatoire dans le nombre de plans possibles. (Je n'ai pas encore essayé)


@wildplasser: Si votre observation est tirée, l'utilité de CTE se développe pour des requêtes très grandes et complexes, où la planification des frais généraux commence à manger des performances. Vous mettriez des sous-sollicitations qui ne seront pas optimisées en CTES pour réduire la complexité de la requête principale. Je vais devoir tester cela quand je trouve le temps.