sql >> Database >  >> RDS >> PostgreSQL

SQL-functie erg traag in vergelijking met query zonder functie-wrapper

user

Tijdens het herschrijven van je functie realiseerde ik me dat je hier kolomaliassen hebt toegevoegd:

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

.. die niets zou doen om te beginnen, aangezien die aliassen onzichtbaar zijn buiten de functie en er niet naar wordt verwezen binnen de functie. Ze zouden dus genegeerd worden. Gebruik voor documentatiedoeleinden beter een opmerking.

Maar het maakt uw zoekopdracht ook ongeldig , omdat user is een volledig gereserveerd woord en kan niet worden gebruikt als kolomalias tenzij tussen dubbele aanhalingstekens.

Vreemd genoeg lijkt de functie in mijn tests te werken met de ongeldige alias. Waarschijnlijk omdat het genegeerd wordt (?). Maar ik weet niet zeker of dit geen bijwerkingen kan hebben.

Uw functie herschreven (anders equivalent):

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;

Het is duidelijk dat de STABLE trefwoord veranderde de uitkomst. Functievolatiliteit zou geen probleem moeten zijn in de testsituatie die u beschrijft. De instelling profiteert normaal gesproken niet van een enkele, geïsoleerde functieaanroep. Lees details in de handleiding. Ook standaard EXPLAIN toont geen zoekplannen voor wat er binnen gebeurt functies. Je zou de extra module auto-explain kunnen gebruiken daarvoor:

  • Postgres-queryplan van een UDF-aanroep geschreven in pgpsql

U heeft een zeer vreemde gegevensdistributie :

auth_web_events tabel heeft 100000000 records, auth_user->2 records, klanten-> 1 record

Aangezien je niet anders hebt gedefinieerd, gaat de functie uit van een schatting van 1000 rijen wordt teruggestuurd. Maar uw functie retourneert eigenlijk slechts 2 rijen . Als al uw oproepen slechts (in de buurt van) 2 rijen terugkeren, declareert u dat gewoon met een toegevoegde ROWS 2 . Kan het zoekplan voor de VOLATILE wijzigen variant ook (zelfs als STABLE is hier sowieso de juiste keuze).



  1. SQL:in clausule in opgeslagen procedure:hoe waarden doorgeven

  2. Oracle 32-bit Client installeren op Windows Server waarop al 64-bit Oracle Database Server wordt uitgevoerd

  3. Postgres INTERVAL met waarde uit tabel

  4. Hoe een JDBC-toepassing te beschermen tegen SQL-injectie?