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

Fonction SQL très lente par rapport à une requête sans wrapper de fonction

user

En réécrivant votre fonction, j'ai réalisé que vous aviez ajouté des alias de colonne ici :

SELECT 
  ...
  auth_user.email AS user, 
  customers.name AS customer,

.. qui ne ferait rien pour commencer, puisque ces alias sont invisibles en dehors de la fonction et non référencés à l'intérieur de la fonction. Ils seraient donc ignorés. À des fins de documentation, mieux vaut utiliser un commentaire.

Mais cela rend également votre requête invalide , car user est un mot entièrement réservé et ne peut pas être utilisé comme alias de colonne à moins d'être entre guillemets.

Bizarrement, dans mes tests, la fonction semble fonctionner avec l'alias invalide. Probablement parce qu'il est ignoré (?). Mais je ne suis pas sûr que cela n'ait pas d'effets secondaires.

Votre fonction réécrite (sinon équivalente) :

CREATE OR REPLACE FUNCTION get_web_events_by_userid(int)
  RETURNS TABLE(
     id int
   , time_stamp timestamptz
   , description text
   , origin text
   , userlogin text
   , customer text
   , client_ip inet
  ) AS
$func$
SELECT w.id
     , w.time_stamp
     , w.description 
     , w.origin  
     , u.email     -- AS user   -- make this a comment!
     , c.name      -- AS customer
     , w.client_ip
FROM   public.auth_user       u
JOIN   public.auth_web_events w ON w.user_id_fk = u.id
JOIN   public.customers       c ON c.id = u.customer_id_fk 
WHERE  u.id = $1   -- reverted the logic here
ORDER  BY w.id DESC
$func$ LANGUAGE sql STABLE;

Évidemment, le STABLE mot-clé a changé le résultat. Volatilité de la fonction ne devrait pas être un problème dans la situation de test que vous décrivez. Le réglage ne profite normalement pas à un seul appel de fonction isolé. Lire les détails dans le manuel. En outre, la norme EXPLAIN n'affiche pas les plans de requête pour ce qui se passe à l'intérieur les fonctions. Vous pouvez utiliser le module supplémentaire auto-explain pour cela :

  • Plan de requête Postgres d'une invocation UDF écrite en pgpsql

Vous avez une distribution de données très étrange :

La table auth_web_events contient 1 000 000 enregistrements, auth_user->2 enregistrements, clients-> 1 enregistrement

Comme vous n'avez rien défini d'autre, la fonction suppose une estimation de 1 000 lignes être retourné. Mais votre fonction ne renvoie en réalité que 2 lignes . Si tous vos appels ne renvoient (aux alentours de) que 2 lignes, déclarez-le simplement avec un ROWS 2 ajouté . Peut changer le plan de requête pour le VOLATILE variante également (même si STABLE est le bon choix de toute façon ici).