Toho lze dosáhnout pomocí jednoduché funkce SQL. Klíčovou vlastností je funkce generate_subscripts()
:
CREATE OR REPLACE FUNCTION f_attendance(_arr2d int[])
RETURNS SETOF attendance AS
$func$
SELECT a.*
FROM generate_subscripts($1, 1) i
JOIN attendance a ON a.class = $1[i][1]
AND a.section = $1[i][2]
$func$ LANGUAGE ROWS 10 sql STABLE;
Volejte:
SELECT * FROM f_attendance(ARRAY[[1,1],[2,2]]);
Nebo totéž s polem literal - což je v některých kontextech výhodnější, zvláště u připravených příkazů:
SELECT * FROM f_attendance('{{1,1},{2,2}}');
Funkce vždy očekává 2D pole. I když minete jeden pár, vnořte jej:
SELECT * FROM f_attendance('{{1,1}}');
Audit vaší implementace
-
Vytvořili jste funkci
VOLATILE
, ale může býtSTABLE
. Podle dokumentace:Kvůli tomuto chování při vytváření snímků funkce obsahující pouze
SELECT
příkazy lze bezpečně označit jakoSTABLE
.Související:
- Jak předat parametr do funkce data
-
Používáte také
LANGUAGE plpgsql
místosql
, což dává smysl, pokud funkci spustíte vícekrát ve stejné relaci. Ale pak to musíte také udělatSTABLE
nebo ztratíte potenciální výkonnostní přínos. Ještě jednou manuál:STABLE
aIMMUTABLE
funkce používají snímek vytvořený na začátku volajícího dotazu, zatímco VOLATILE funkce získávají čerstvý snímek na začátku každého dotazu, který provádějí. -
Váš
EXPLAIN
výstup zobrazuje Prohledávání pouze indexu , ne sekvenční skenování, jak předpokládáte ve svém komentáři. -
V
EXPLAIN
je také krok řazení výstup, který neodpovídá kódu, který ukazujete. Jste si jisti, že jste zkopírovali správnýEXPLAIN
? výstup? Jak jsi to vůbec získal? Funkce PL/pgSQL jsou černá políčka proEXPLAIN
. Použili jsteauto_explain
? Podrobnosti:- Plán dotazů Postgres pro vyvolání UDF napsaný v pgpsql
-
Plánovač dotazů Postgres netuší, kolik prvků pole bude mít předaný parametr, takže je těžké naplánovat dotaz a může se stát, že bude výchozí sekvenční skenování (v závislosti na více faktorech). Můžete si pomoci deklarováním očekávaného počtu řádků. Pokud obvykle nemáte více než 10 položek, přidejte
ROWS 10
jako jsem to udělal teď výše. A znovu otestujte.