Нет подсказки для создания плана выполнения, который игнорирует планы в общем пуле. Более распространенный способ сформулировать этот вопрос: как заставить Oracle всегда выполнять жесткий анализ?
В некоторых странных ситуациях такое поведение требуется. Было бы полезно полностью объяснить причину, по которой вам это нужно, поскольку решение варьируется в зависимости от того, зачем вам это нужно.
- Странная проблема с производительностью. Oracle выполняет некоторую динамическую повторную оптимизациюОператоры SQL после первого запуска, такие как адаптивное совместное использование курсора и обратная связь по количеству элементов. В редких случаях, когда эти функции имеют обратный эффект, вы можете их отключить.
- Динамический запрос. У вас есть динамический запрос, который использует картридж данных Oracle для извлечения данных на этапе разбора, но Oracleне будет выполнять шаг разбора, потому что запрос выглядит статическим для Oracle.
- Недоразумение. Что-то пошло не так, и это проблема XY.
Решения
Самый простой способ решить эту проблему -используя решение Торстена Кеттнера об изменении запроса каждый раз.
Если это не вариант, второе простейшее решение - сбросить запрос из общего пула, например:
--This only works one node at a time.
begin
for statements in
(
select distinct address, hash_value
from gv$sql
where sql_id = '33t9pk44udr4x'
order by 1,2
) loop
sys.dbms_shared_pool.purge(statements.address||','||statements.hash_value, 'C');
end loop;
end;
/
Еслиу вас нет контроля над SQL, и вам нужно решить проблему с помощью решения в стиле побочных эффектов. Джонатан Льюис и Рэндольф Гейст имеют решение с использованием виртуальной частной базы данных , которое добавляет уникальный предикат к каждому оператору SQLна конкретном столе. Вы просили что-то странное, вот странное решение. Buckle up.
-- Create a random predicate for each query on a specific table.
create table hard_parse_test_rand as
select * from all_objects
where rownum <= 1000;
begin
dbms_stats.gather_table_stats(null, 'hard_parse_test_rand');
end;
/
create or replace package pkg_rls_force_hard_parse_rand is
function force_hard_parse (in_schema varchar2, in_object varchar2) return varchar2;
end pkg_rls_force_hard_parse_rand;
/
create or replace package body pkg_rls_force_hard_parse_rand is
function force_hard_parse (in_schema varchar2, in_object varchar2) return varchar2
is
s_predicate varchar2(100);
n_random pls_integer;
begin
n_random := round(dbms_random.value(1, 1000000));
-- s_predicate := '1 = 1';
s_predicate := to_char(n_random, 'TM') || ' = ' || to_char(n_random, 'TM');
-- s_predicate := 'object_type = ''TABLE''';
return s_predicate;
end force_hard_parse;
end pkg_rls_force_hard_parse_rand;
/
begin
DBMS_RLS.ADD_POLICY (USER, 'hard_parse_test_rand', 'hard_parse_policy', USER, 'pkg_rls_force_hard_parse_rand.force_hard_parse', 'select');
end;
/
alter system flush shared_pool;
Вы можете увидеть жесткий анализ в действии, выполнив один и тот же запрос несколько раз:
select * from hard_parse_test_rand;
select * from hard_parse_test_rand;
select * from hard_parse_test_rand;
select * from hard_parse_test_rand;
Теперь в GV $ SQL есть три записи для каждого выполнения,В виртуальной частной базе данных есть странное поведение, которое анализирует запрос несколько раз, хотя окончательный текст выглядит одинаково.
select *
from gv$sql
where sql_text like '%hard_parse_test_rand%'
and sql_text not like '%quine%'
order by 1;