Rozważmy następującą kwerendę sql:Inteligentne zapytań logicznych przy wykorzystaniu funkcji wewnątrz PostgreSQL
SELECT a,b,c
FROM t
WHERE (id1 = :p_id1 OR :p_id1 IS NULL) AND (id2 = :p_id2 OR :p_id2 IS NULL)
Markus Winand w swojej książce „SQL Performance explained” names to podejście jako jeden z najgorszych wyników anty-wzorców wszech i wyjaśnia dlaczego (baza danych musi przygotować plan na najgorszy przypadek, gdy wszystkie filtry są wyłączone).
Ale później pisze również, że dla PostgreSQL ten problem występuje tylko przy ponownym użyciu instrukcji (PreparedStatement
) obsługi.
Załóżmy też teraz, że zapytanie to jest zawinięty do funkcji, coś jak:
CREATE FUNCTION func(IN p_id1 BIGINT,IN p_id2 BIGINT)
...
$BODY$
BEGIN
...
END;
$BODY$
tej pory mam niezrozumienie kilku punktach:
Czy ten problem nadal występuje w przypadku funkcja owijania? (Próbowałem zobaczyć plan wykonania dla wywołania funkcji, ale Postgres nie pokazuje mi szczegółów wewnętrznych wywołań funkcji, nawet z
SET auto_explain.log_nested_statements = ON
).Załóżmy, że pracuję nad starszym projektem i nie mogę zmienić samej funkcji, tylko kod wykonawczy Java. Czy lepiej będzie unikać tutaj przygotowanego wyciągu i za każdym razem używać zapytania dynamicznego? (Zakładając, że czas wykonania jest dość długi, do kilku sekund). Powiedzieć, prawdopodobnie brzydki podejście:
getSession().doWork(connection -> {
ResultSet rs = connection.createStatement().executeQuery("select * from func("+id1+","+id2+")");
...
})
Dziękujemy za odpowiedź. Odnośnie pierwszego punktu, nie do końca rozumiem. Czy to oznacza, że opisany problem ogólnie nie jest problemem dla PostgreSQL, gdy tego typu zapytania są pakowane w funkcję? – Andremoniy
To naprawdę zależy od szczęścia. Powiedzmy, że zapytanie ma jeden parametr i bardzo potrzebuje różnych planów dla wartości A i B. Na przykład A prosi o skanowanie sekwencyjne (wysokie koszty), a B korzysta ze skanowania indeksu (niski koszt). Ogólny plan wykorzystuje skanowanie sekwencyjne. Wykonujesz F (A) 5 razy, a planista decyduje, że można przejść do planu ogólnego. Teraz masz problem: F (B) nie użyje skanowania indeksu. Ale jeśli zadzwonisz do F (A), F (B), F (A), F (B) i tak dalej, średni koszt własny będzie mniejszy niż koszt ogólnego planu i jesteś bezpieczny. –
Dobra, ale myślę, że zawsze powinniśmy rozważyć najgorszy przypadek, nieprawdaż? Wygląda na to, że w najgorszym przypadku nadal będzie to problemem. I czy poprawnie rozumiem, że dla funkcji plan zostanie obliczony niezależnie od użycia przygotowanego wyciągu? – Andremoniy