Czy Oracle może ponownie wykorzystać wynik funkcji, gdy jest wywoływany w tym samym zapytaniu (transakcji?) Bez użycia pamięci podręcznej wyników funkcji?Wydajność Oracle: zapytanie wywołujące wiele identycznych wywołań funkcji
Aplikacja, z którą pracuję, jest silnie uzależniona od funkcji Oracle. Wiele zapytań kończy wiele razy wykonywanie tych samych funkcji.
Typowym przykładem może być:
SELECT my_package.my_function(my_id),
my_package.my_function(my_id)/24,
my_package.function_also_calling_my_function(my_id)
FROM my_table
WHERE my_table.id = my_id;
Zauważyłem, że Oracle zawsze wykonuje każdy z tych funkcji, nie zdając sobie sprawy, że ta sama funkcja została wywołana tylko sekundy temu w tej samej kwerendy. Możliwe, że niektóre elementy funkcji zostaną zbuforowane, co spowoduje nieco szybszy powrót. Nie dotyczy to mojego pytania, ponieważ chcę uniknąć całej drugiej lub trzeciej egzekucji.
Założono, że funkcje są dość zasobochłonne i że te funkcje mogą wywoływać więcej funkcji, opierając ich wynik na tabelach, które są rozsądnie duże i z częstymi aktualizacjami (milion rekordów, aktualizacje z powiedzeniem 1000 aktualizacji na godzinę). Z tego powodu nie można korzystać z pamięci podręcznej wyników funkcji Oracle.
Mimo że dane często się zmieniają, oczekuję, że wynik tych funkcji będzie taki sam, gdy zostaną wywołane z tego samego zapytania.
Czy Oracle może ponownie wykorzystać wyniki tych funkcji i w jaki sposób? Używam Oracle11g i Oracle12c.
Poniżej jest przykład (tylko przypadkowa funkcja non-sense do zilustrowania problemu):
-- Takes 200 ms
SELECT test_package.testSpeed('STANDARD', 'REGEXP_COUNT')
FROM dual;
-- Takes 400ms
SELECT test_package.testSpeed('STANDARD', 'REGEXP_COUNT')
, test_package.testSpeed('STANDARD', 'REGEXP_COUNT')
FROM dual;
używanych funkcji:
CREATE OR REPLACE PACKAGE test_package IS
FUNCTION testSpeed (p_package_name VARCHAR2, p_object_name VARCHAR2)
RETURN NUMBER;
END;
/
CREATE OR REPLACE PACKAGE BODY test_package IS
FUNCTION testSpeed (p_package_name VARCHAR2, p_object_name VARCHAR2)
RETURN NUMBER
IS
ln_total NUMBER;
BEGIN
SELECT SUM(position) INTO ln_total
FROM all_arguments
WHERE package_name = 'STANDARD'
AND object_name = 'REGEXP_COUNT';
RETURN ln_total;
END testSpeed;
END;
/
Można nadal używać buforowania wynik i „relies_on” słowo kluczowe do obsługi zmian w tabeli - http://www.oracle.com/technetwork/issue-archive/2010/10-sep/o57plsql-088600.html Dlaczego nie wywołać funkcji raz używając klauzuli WITH, a następnie odwołać się do zapytania? – OldProgrammer
W 12c można zadeklarować funkcję WEWNĄTRZ instrukcji SQL, która jest czymś BARDZO różniącym się od PL/SQL (z perspektywy transakcyjnej). – ibre5041
Używanie klauzuli WITH nie pomaga, ponieważ nadal dwa razy wykonuje tę funkcję. Nie widzę, jak słowo kluczowe RELIES_ON zmienia cokolwiek, w zależnościach 11gR2 są automatycznie identyfikowane, a tabela wielokrotnie zmienia dane, unieważniając pamięć podręczną. Szukam specjalnie dla buforowania w ramach tego samego zapytania. Klauzula 12c WITH FUNCTION jest interesująca i mógłbym ją zastosować tu i tam, ale nie rozwiązuje większego problemu, chociaż funkcje z zagnieżdżonymi funkcjami są naprawdę skomplikowane i wykorzystują framework aplikacji, w której pracuję. – jmuntingh