sql >> Databáze >  >> RDS >> PostgreSQL

Funkce SQL velmi pomalá ve srovnání s dotazem bez funkce wrapper

user

Při přepisování vaší funkce jsem si uvědomil, že jste sem přidali aliasy sloupců:

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

.. který neudělá nic pro začátek, protože tyto aliasy jsou mimo funkci neviditelné a uvnitř funkce se na ně neodkazuje. Takže by byli ignorováni. Pro účely dokumentace je lepší použít komentář.

Váš dotaz však také neplatný , protože user je zcela rezervované slovo a nelze jej použít jako alias sloupce, pokud není uveden ve dvojitých uvozovkách.

Kupodivu se v mých testech zdá, že funkce funguje s neplatným aliasem. Pravděpodobně proto, že je ignorován (?). Ale nejsem si jistý, že to nemůže mít vedlejší účinky.

Vaše funkce přepsána (jinak ekvivalentní):

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;

Je zřejmé, že STABLE klíčové slovo změnilo výsledek. Nestálost funkcí by neměl být problém v testovací situaci, kterou popisujete. Nastavení normálně nepřináší jediné, izolované volání funkce. Podrobnosti si přečtěte v návodu. Také standardní EXPLAIN nezobrazuje plány dotazů na to, co se děje uvnitř funkcí. Můžete použít přídavný modul automatické vysvětlení za to:

  • Plán dotazů Postgres pro vyvolání UDF napsaný v pgpsql

Máte velmi zvláštní rozložení dat :

Tabulka auth_web_events má 10 000 000 záznamů, auth_user->2 záznamy, zákazníci-> 1 záznam

Protože jste nedefinovali jinak, funkce předpokládá odhad 1000 řádků být vrácen. Vaše funkce však ve skutečnosti vrací pouze 2 řádky . Pokud všechna vaše volání vracejí pouze (v blízkosti) 2 řádky, stačí to deklarovat přidáním ROWS 2 . Může změnit plán dotazů pro VOLATILE varianta také (i když STABLE je zde každopádně správná volba).



  1. data načtená z databáze SQLitE se neukládají v modelové třídě ArrayList android

  2. Zkontrolujte, zda tabulka obsahuje cizí klíč na serveru SQL pomocí OBJECTPROPERTY()

  3. SPOUŠTĚČE, které způsobují selhání INSERTů? Možný?

  4. Programově načíst zdroj uložené procedury SQL Server, který je identický se zdrojem vráceným uživatelským rozhraním SQL Server Management Studio?