是否提示忽略来自共享池的现有执行计划来生成执行计划? [英] Is there a hint to generate execution plan ignoring the existing one from shared pool?

查看:53
本文介绍了是否提示忽略来自共享池的现有执行计划来生成执行计划?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否提示忽略共享池中的现有执行计划来生成执行计划?

推荐答案

不提示创建忽略共享池中计划的执行计划。表达此问题的一种更常见的方式是:如何让Oracle始终执行硬解析?

有几种奇怪的情况需要此行为。详细解释您需要此解决方案的原因会很有帮助,因为解决方案会根据您需要它的原因而有所不同。

  1. 奇怪的性能问题。Oracle在第一次运行后对SQL语句执行一些动态重新优化,如自适应游标共享和基数反馈。在这些功能适得其反的极少数情况下,您可能需要禁用它们。
  2. 动态查询。您有一个使用ORACLE数据盒式磁带在分析步骤中提取数据的动态查询,但ORACLE不会执行该分析步骤,因为该查询在ORACLE看来像静电。
  3. 误解。出现问题,这是XY问题。

解决方案

解决此问题的最简单方法是使用Thorsten Kettner的每次更改查询的解决方案。

如果这不是一个选项,第二个最简单的解决方案是从共享池刷新查询,如下所示:

--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,并且需要使用副作用样式的解决方案修复问题,Jonathan Lewis和Randolf Geist有一个solution using Virtual Private Database,它为特定表上的每个SQL语句添加一个惟一的谓词。你要了些奇怪的东西,这里有个奇怪的解决方案。系好安全带。

-- 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;

这篇关于是否提示忽略来自共享池的现有执行计划来生成执行计划?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆