PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Funzione SQL molto lenta rispetto alla query senza wrapper di funzioni

user

Durante la riscrittura della tua funzione mi sono reso conto che hai aggiunto alias di colonna qui:

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

.. che non farebbe nulla tanto per cominciare, poiché quegli alias sono invisibili all'esterno della funzione e non referenziati all'interno della funzione. Quindi verrebbero ignorati. Ai fini della documentazione meglio utilizzare un commento.

Ma rende anche la tua query non valida , perché user è una parola completamente riservata e non può essere utilizzato come alias di colonna a meno che non sia doppiato tra virgolette.

Stranamente, nei miei test la funzione sembra funzionare con l'alias non valido. Probabilmente perché è ignorato (?). Ma non sono sicuro che questo non possa avere effetti collaterali.

La tua funzione riscritta (altrimenti equivalente):

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;

Ovviamente, il STABLE la parola chiave ha cambiato il risultato. Volatilità delle funzioni non dovrebbe essere un problema nella situazione di test che descrivi. L'impostazione normalmente non giova a una singola chiamata di funzione isolata. Leggi i dettagli nel manuale. Inoltre, lo standard EXPLAIN non mostra i piani di query per ciò che sta accadendo dentro funzioni. Potresti utilizzare il modulo aggiuntivo spiegazione automatica per quello:

  • Piano di query Postgres di una chiamata UDF scritta in pgpsql

Hai una distribuzione dei dati molto strana :

La tabella auth_web_events ha 100000000 record, auth_user->2 record, clients-> 1 record

Poiché non hai definito diversamente, la funzione presuppone una stima di 1000 righe da restituire. Ma la tua funzione in realtà restituisce solo 2 righe . Se tutte le tue chiamate restituiscono solo (in prossimità di) 2 righe, dichiaralo semplicemente con un ROWS 2 aggiunto . Potrebbe cambiare il piano di query per VOLATILE anche variante (anche se STABLE è comunque la scelta giusta qui).