将指定SQL的执行计划从共享池删除的方法

如果Oracle的优化器产生了某种错误的执行计划,或者我们希望Oracle对于某个SQL重新进行分析,那么就需要这个SQL的执行计划在共享池中过期,而简单的方法在10.2.0.4以后才出现。

对于以前的版本而言,最显而易见的方法莫过于直接刷新共享池,但是如果是数据库中绝大部分的SQL都存在问题,那么这种方法无可厚非,也可能是见效最快的方法,而如果数据库中仅仅是个别的SQL存在问题,那么这种方法就过于暴力了。

SQL> select count(*) from dual;

COUNT(*)

----------

1

SQL> select sql_id, address, hash_value, executions, loads, parse_calls, invalidations

2 from v$sqlarea

3 where sql_text = ‘select count(*) from dual‘;

SQL_ID ADDRESS HASH_VALUE EXECUTIONS LOADS PARSE_CALLS INVALIDATIONS

------------- ---------------- ---------- ---------- ---------- ----------- -------------

4m94ckmu16f9k 00000000B6C61FC0 4094900530 1 1 1 0

SQL> select count(*) from v$sqlarea;

COUNT(*)

----------

3061

SQL> alter system flush shared_pool;

System altered.

SQL> select sql_id, address, hash_value, executions, loads, parse_calls, invalidations

2 from v$sqlarea

3 where sql_text = ‘select count(*) from dual‘;

no rows selected

SQL> select count(*) from v$sqlarea;

COUNT(*)

----------

37

为了一个SQL而清空整个共享池,这个代价确实太大了,何况对于一个繁忙的OLTP系统而言,这个刷新共享池的操作所带来的风险和后果与直接关闭数据库相比,也没有太大的差别。

那么有没有细粒度一点的办法呢,其实方法有很多,相关表上任何的DDL都会导致SQL执行计划的失效,但是DDL本身风险就毕竟高,如果想要对系统影响最小,那么这个DDL就非GRANT莫属。只需要当前用户将这个表的权限授权给自己,就可以达到想要的效果:

SQL> select count(*) from dual;

COUNT(*)

----------

1

SQL> select sql_id, address, hash_value, executions, loads, parse_calls, invalidations

2 from v$sqlarea

3 where sql_text = ‘select count(*) from dual‘;

SQL_ID ADDRESS HASH_VALUE EXECUTIONS LOADS PARSE_CALLS INVALIDATIONS

------------- ---------------- ---------- ---------- ---------- ----------- -------------

4m94ckmu16f9k 00000000B6C61FC0 4094900530 1 1 1 0

SQL> select 1 from dual;

1

----------

1

SQL> select * from dual;

D

-

X

SQL> select ‘a‘ from dual;

-

a

SQL> select count(1) from dual;

COUNT(1)

----------

1

SQL> select sql_id, address, hash_value, executions, loads, parse_calls, invalidations

2 from v$sqlarea

3 where lower(sql_text) like ‘%dual%‘;

SQL_ID ADDRESS HASH_VALUE EXECUTIONS LOADS PARSE_CALLS INVALIDATIONS

------------- ---------------- ---------- ---------- ---------- ----------- -------------

gr7s3j0cg8pr6 00000000B6A5A470 418666214 1 1 1 0

40p7rprfbt1as 00000000B69BDC38 3703342424 1 1 1 0

520mkxqpf15q8 00000000B6DD9610 2866845384 1 1 1 0

ak90gdq0udv37 00000000B6E3C6B0 2175200359 2 2 2 1

4m94ckmu16f9k 00000000B6C61FC0 4094900530 1 1 1 0

a5ks9fhw2v9s1 00000000B698DA88 942515969 1 1 1 0

800hwktjz3zuc 00000000B6999268 1676803916 1 1 1 0

7 rows selected.

SQL> grant select on dual to sys;

grant select on dual to sys

*

ERROR at line 1:

ORA-01749: you may not GRANT/REVOKE privileges to/from yourself

SQL> grant select on dual to public;

Grant succeeded.

SQL> select sql_id, address, hash_value, executions, loads, parse_calls, invalidations

2 from v$sqlarea

3 where lower(sql_text) like ‘%dual%‘;

SQL_ID ADDRESS HASH_VALUE EXECUTIONS LOADS PARSE_CALLS INVALIDATIONS

------------- ---------------- ---------- ---------- ---------- ----------- -------------

gr7s3j0cg8pr6 00000000B6A5A470 418666214 2 1 2 0

ak90gdq0udv37 00000000B6E3C6B0 2175200359 2 2 2 1

对于其他用户而言,都可以使用将表的查询权限授权给OWNER本身的方法,但是测试用户本身为SYS,因此需要其他用户授权,方便起见使用了授权给PUBLIC的方式。可以看到,这种方式同样可以生效,但是仍然存在打击面过大的问题。对于系统中一个频繁访问的表,很可能这个授权的操作,导致少则几十,多则几百个SQL都是失效,这个风险仍然不可小觑。

那么对于就没有一个可以将粒度控制在SQL本身上的方法吗?在11g中,Oracle的DBMS_SHARED_POOL包新增了PURGE功能,可以完美的解决这个问题,这个方法在10.2.0.4和10.2.0.5补丁集中也被添加进来,使得10.2的高版本同样可以实现这个功能,使用方法很简单:

SQL> select count(*) from dual;

COUNT(*)

----------

1

SQL> select sql_id, address, hash_value, executions, loads, parse_calls, invalidations

2 from v$sqlarea

3 where sql_text = ‘select count(*) from dual‘;

SQL_ID ADDRESS HASH_VALUE EXECUTIONS LOADS PARSE_CALLS INVALIDATIONS

------------- ---------------- ---------- ---------- ---------- ----------- -------------

4m94ckmu16f9k 00000000B6C61FC0 4094900530 1 2 1 1

SQL> select 1 from dual;

1

----------

1

SQL> select * from dual;

D

-

X

SQL> select sql_id, address, hash_value, executions, loads, parse_calls, invalidations

2 from v$sqlarea

3 where lower(sql_text) like ‘%dual%‘;

SQL_ID ADDRESS HASH_VALUE EXECUTIONS LOADS PARSE_CALLS INVALIDATIONS

------------- ---------------- ---------- ---------- ---------- ----------- -------------

gr7s3j0cg8pr6 00000000B6A5A470 418666214 3 1 3 0

520mkxqpf15q8 00000000B6DD9610 2866845384 1 2 1 1

ak90gdq0udv37 00000000B6E3C6B0 2175200359 3 2 3 1

4m94ckmu16f9k 00000000B6C61FC0 4094900530 1 2 1 1

a5ks9fhw2v9s1 00000000B698DA88 942515969 1 2 1 1

SQL> exec dbms_shared_pool.purge(‘00000000B6C61FC0,4094900530‘, ‘c‘)

PL/SQL procedure successfully completed.

SQL> select sql_id, address, hash_value, executions, loads, parse_calls, invalidations

2 from v$sqlarea

3 where lower(sql_text) like ‘%dual%‘;

SQL_ID ADDRESS HASH_VALUE EXECUTIONS LOADS PARSE_CALLS INVALIDATIONS

------------- ---------------- ---------- ---------- ---------- ----------- -------------

gr7s3j0cg8pr6 00000000B6A5A470 418666214 4 1 4 0

520mkxqpf15q8 00000000B6DD9610 2866845384 1 2 1 1

ak90gdq0udv37 00000000B6E3C6B0 2175200359 3 2 3 1

a5ks9fhw2v9s1 00000000B698DA88 942515969 1 2 1 1

过程PURGE的第一个参数为V$SQLAREA中用逗号分隔的ADDRESS列和HASH_VALUE列的值,第二个参数’c’表示PURGE的对象是CURSOR,不过实际上这里可以使用除了P(PROCEDURE/FUNCTION/PACKAGE)、T(TYPE)、R(TRIGGER)和Q(SEQUENCE)的任何值  www.2cto.com

使用这种方法,就可以精确的将一个SQL从共享池中删除,从而使得Oracle为这个SQL重新生成执行计划。这种方法只针对单个SQL语句,使得解决问题的同时不会造成任何的误伤。

不过需要注意一点,在10.2.0.4中,虽然PURGE过程已经存在,但是要使这个过程可以真正的生效,还必须设置一个EVENT:

SQL> alter system set event = ‘5614566 trace name context forever‘ scope = spfile;

System altered.

设置EVENT后需要重启,DBMS_SHARED_POOL的PURGE才可以生效。也就是说,除非提前进行过设置,否则这个PURGE的功能对于一个产品环境而言,必须在10.2.0.5以上版本才可以使用。

时间: 2024-11-03 22:29:29

将指定SQL的执行计划从共享池删除的方法的相关文章

ORACLE从共享池删除指定SQL的执行计划

Oracle 11g在DBMS_SHARED_POOL包中引入了一个名为PURGE的新存储过程,用于从对象库缓存中刷新特定对象,例如游标,包,序列,触发器等.也就是说可以删除.清理特定SQL的执行计划,这样在特殊情况下,就避免你要将整个SHARED POOL清空的危险情况.例如某个SQL语句由于优化器产生了错误的执行计划,我们希望优化器重新解析,生成新的执行计划,必须先将SQL的执行计划从共享池中刷出或将其置为无效,那么优化器才能将后续SQL进行硬解析.生成新的执行计划.这在以前只能使用清空共享

如何清除某条SQL的执行计划

如果遇到绑定窥探导致执行计划慢的情况,想要清除某条SQL的执行计划,让它硬解析,找了很久都没有找到直接操作share pool的方法(除非alter system flush shared_pool),只能通过对表ddl使SQL硬解析.现在终于找到了,使用sys.dbms_shared_pool.purge 在11g下可以直接使用,但在10g上需要 alter session set events '5614566 trace name context forever'   --特定游标对象 S

SQL Server 执行计划缓存

原文:SQL Server 执行计划缓存 标签:SQL SERVER/MSSQL SERVER/数据库/DBA/内存池/缓冲区 概述 了解执行计划对数据库性能分析很重要,其中涉及到了语句性能分析与存储,这也是写这篇文章的目的,在了解执行计划之前先要了解一些基础知识,所以文章前面会讲一些概念,学起来会比较枯燥,但是这些基础知识非常重要. 目录 概述 基础概念 怎样缓存执行计划 SQL Server自动删除执行计划 重新编译执行计划 测试 执行计划相关系统视图 手动清空缓存执行计划 测试索引更改对执

Oracle固定SQL的执行计划(一)---SQL Profile

我们都希望对于所有在Oracle数据库中执行的SQL,CBO都能产生出正确的执行计划,但实际情况却并非如此,由于各种各样的原因(比如目标SQL所涉及的对象的统计信息的不准确,或者CBO内部一些成本计算公式的先天缺陷等),导致有时CBO产生效率不高.甚至是错误的执行计划.特别是CBO对目标SQL所产生的初始执行计划是正确的,后来由于某种原因(比如统计信息的变更等)而导致CBO重新对其产生了错误的执行计划,这种执行计划的改变往往会导致目标SQL执行时间呈数量级的递增,而且常常会让我们很困惑:这个SQ

SQL Server执行计划那些事儿(3)——书签查找

接下来的文章是记录自己曾经的盲点,同时也透漏了自己的发展历程(可能发展也算不上,只能说是瞎混).当然,一些盲点也在工作和探究过程中慢慢有些眉目,现在也愿意发扬博客园的奉献精神,拿出来和大家分享一下. 在刚开始工作时候,总以自己有个“高科技”的工作,而感到特别神气,经常在其他人面前说一些让别人觉得高大上的措辞,到后来会在学妹面前炫耀的讲一下SQL Server的执行计划,这个时候别说执行计划了,就是SQL的优化对我来说还是个新鲜的事物,总是以自己能正确查出结果而沾沾自喜.然而,当真有不经世事的学妹

SQL Server执行计划那些事儿(2)——查找和扫描

接下来的文章是记录自己曾经的盲点,同时也透漏了自己的发展历程(可能发展也算不上,只能说是瞎混).当然,一些盲点也在工作和探究过程中慢慢有些眉目,现在也愿意发扬博客园的奉献精神,拿出来和大家分享一下. 开门见上,直接入题 在查看执行计划时候,你是否曾经也和我一样,有这样的疑惑呢?查找和扫描究竟是什么,以及他们的在查询性能上有什么区别.下面分享下我的理解. 扫描和查找是SQL Server从表或索引中读取数据所采用的迭代器,又因为经常在执行计划中看到,因此理解他们之间的区别,对我们优化查询有很重要的

Oracle 11g如何清除share pool中某条SQL的执行计划

以前在10g数据库上,如果遇到绑定窥探导致执行计划慢的情况,想要清除某条SQL的执行计划,让它硬解析,找了很久都没有找到直接操作share pool的方法(总不能alter system flush shared_pool),只能通过对表ddl使SQL硬解析.现在终于找到了,使用sys.dbms_shared_pool.purge,在11g下可以直接使用,但在10g上需要alter session set events '5614566 trace name context forever'.

查询oracle sql的执行计划时,一个很重要的视图--dba_hist_sql_plan

本文的编写得到枯荣长老的大力帮助,在此表示感谢. 本文适用的oracle db版本为oracle 10g或者更高版本. 之所以说这个视图很重要,是因为该视图中有一列是在awrsqrpt报告中没有的.这一列就是 filter_predicates列. SELECT plan_hash_value, TO_CHAR(RAWTOHEX(child_address)), TO_NUMBER(child_number), id, LPAD(' ', DEPTH) || operation operatio

sql server 执行计划(execution plan)介绍

sql server 执行计划(execution plan)介绍 大纲:目的介绍sql server 中执行计划的大致使用,当遇到查询性能瓶颈时,可以发挥用处,而且带有比较详细的学习文档和计划,阅读者可以按照我计划进行,从而达到对执行计划一个比较系统的学习. 什么是sql server 执行计划 sql server 执行计划的大致使用 学习计划 1.什么是sql server 执行计划 执行计划是查询优化器对我们提交的T-SQL查询请求的最有效方法的的执行结果,执行计划可以告诉我们查询是如何