千家信息网

Oracle删除一条SQL在Shared Pool里缓存的执行计划的三种方法

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,在Oracle里第一次执行一条SQL语句后,该SQL语句会被硬解析,而且执行计划和解析树会被缓存到Shared Pool里。方便以后再次执行这条SQL语句时不需要再做硬解析,方便应用系统的扩展。但是如
千家信息网最后更新 2026年11月03日Oracle删除一条SQL在Shared Pool里缓存的执行计划的三种方法

在Oracle里第一次执行一条SQL语句后,该SQL语句会被硬解析,而且执行计划和解析树会被缓存到Shared Pool里。方便以后再次执行这条SQL语句时不需要再做硬解析,方便应用系统的扩展。但是如果该SQL对应的表数据量突变或其他原因,Shared Pool里缓存的执行计划和解析树已经不再适用于现在的情况,SQL执行效率急速下降,这种情况下就需要把该SQL缓存在Shared Pool里的执行计划和解析树清理出去,以便对该SQL重新做硬解析,生成新的执行计划和解析树。

从Shared Pool删除SQL缓存的执行计划有三种方法:

  • alter system flush shared_pool;

  • 对表做DDL操作

  • dbms_shared_pool.purge包(10.2.0.4及其以上)

上面三种方法的影响范围依次递减,下面分别用实例做演示

创建测试表

zx@MYDB>create table s1 as select * from dba_objects;Table created.zx@MYDB>create table s2 as select * from dba_objects;Table created.

1、alter system flush shared_pool;

这条命令是清除Shared Pool里缓存的所有数据,自然可以删除想要删除的SQL对就的执行计划,但负作用是它把Shared Pool里的所有数据都清除了,影响太大。生产系统一定要谨慎使用这个命令。

执行两个查询,并查看在Shared Pool里的缓存

zx@MYDB>select object_name from s1 where object_id=20;OBJECT_NAME------------------------------ICOL$zx@MYDB>select object_name from s2 where object_id=20;OBJECT_NAME------------------------------ICOL$zx@MYDB>col sql_text for a80zx@MYDB>select sql_text,sql_id,version_count,executions from v$sqlarea where sql_text like 'select object_name from s%';SQL_TEXT                                                                         SQL_ID                                VERSION_COUNT EXECUTIONS-------------------------------------------------------------------------------- --------------------------------------- ------------- ----------select object_name from s1 where object_id=20                                   1s45nwjtws2tj                                          1         1select object_name from s2 where object_id=20                                   a6gw4ht2unxun                                          1         1zx@MYDB>select object_name from s1 where object_id=20;OBJECT_NAME------------------------------ICOL$zx@MYDB>select sql_text,sql_id,version_count,executions from v$sqlarea where sql_text like 'select object_name from s%';SQL_TEXT                                                                         SQL_ID                                VERSION_COUNT EXECUTIONS-------------------------------------------------------------------------------- --------------------------------------- ------------- ----------select object_name from s1 where object_id=20                                   1s45nwjtws2tj                                          1         2select object_name from s2 where object_id=20                                   a6gw4ht2unxun                                          1         1

上面查询分别对表s1和表s2做查询,从输出可以看出上面执行的两个SQL的执行计划和解析树被缓存到了Shared Pool中,再次执行时会直接用缓存的执行计划(EXECUTIONS变为2)。现在想删除表s1对应SQL的执行计划,执行alter system flush shared_pool;

zx@MYDB>alter system flush shared_pool;System altered.zx@MYDB>select sql_text,sql_id,version_count,executions from v$sqlarea where sql_text like 'select object_name from s%';no rows selected

从上面查询结果可以看出命令确实删除了s1对应SQL的执行计划,但同时也把表s2对应的SQL的执行计划也删除了,伤及了无辜。

2、对表做DDL操作

一旦对某个表执行了DDL操作,库缓存中所有在SQL文本中包含了这个表的Shared Cursor都会被Oracle标记为失效(invalid),这意味着这些Shared Cursor中存储的解析树和执行计划将不再能被重用,所以当Oracle再次执行与这个表相关的SQL时就会使用硬解析。但这种方法的弊端在于其影响范围还是太广,因为一旦对某个表执行了DDL操作,再次执行与这个表相关的所有SQL时就会全部使用硬解析。这是很不好的,特别是对于OLTP类型的应用系统而言,因为这可能会导致短时间内的硬解析数量剧增,进而影响系统的性能。

zx@MYDB>select object_name from s1 where object_id=20;OBJECT_NAME------------------------------ICOL$zx@MYDB>select object_name from s1 where object_id=30;OBJECT_NAME------------------------------I_COBJ#zx@MYDB>select sql_text,sql_id,version_count,executions from v$sqlarea where sql_text like 'select object_name from s%';SQL_TEXT                                                                         SQL_ID                                VERSION_COUNT EXECUTIONS-------------------------------------------------------------------------------- --------------------------------------- ------------- ----------select object_name from s1 where object_id=20                                   1s45nwjtws2tj                                          1         1select object_name from s1 where object_id=30                                   1hdyqyxhtavqs                                          1         1zx@MYDB>select object_name from s1 where object_id=20;OBJECT_NAME------------------------------ICOL$zx@MYDB>select sql_text,sql_id,version_count,executions from v$sqlarea where sql_text like 'select object_name from s%';SQL_TEXT                                                                         SQL_ID                                VERSION_COUNT EXECUTIONS-------------------------------------------------------------------------------- --------------------------------------- ------------- ----------select object_name from s1 where object_id=20                                   1s45nwjtws2tj                                          1         2select object_name from s1 where object_id=30                                   1hdyqyxhtavqs                                          1         1

上面查询对表s1做了两个不同的查询,从输出可以看出上面执行的两个SQL的执行计划和解析树被缓存到了Shared Pool中,再次执行时会直接用缓存的执行计划(EXECUTIONS变为2)。现在要删除object_id=20对应SQL的执行计划,这里选择对表添加注释(COMMENT),它也是DDL操作。

zx@MYDB>comment on table s1 is 'test shared cursor';Comment created.zx@MYDB>select sql_text,sql_id,version_count,executions,OBJECT_STATUS from v$sqlarea where sql_text like 'select object_name from s%';SQL_TEXT                                                                         SQL_ID                                VERSION_COUNT EXECUTIONS OBJECT_STATUS-------------------------------------------------------------------------------- --------------------------------------- ------------- ---------- ---------------select object_name from s1 where object_id=20                                   1s45nwjtws2tj                                          1         2 INVALID_UNAUTHselect object_name from s1 where object_id=30                                   1hdyqyxhtavqs                                          1         1 INVALID_UNAUTHzx@MYDB>select object_name from s1 where object_id=20;OBJECT_NAME------------------------------ICOL$zx@MYDB>select sql_text,sql_id,version_count,executions,OBJECT_STATUS from v$sqlarea where sql_text like 'select object_name from s%';SQL_TEXT                                                                         SQL_ID                                VERSION_COUNT EXECUTIONS OBJECT_STATUS-------------------------------------------------------------------------------- --------------------------------------- ------------- ---------- ---------------select object_name from s1 where object_id=20                                   1s45nwjtws2tj                                          1         1 VALIDselect object_name from s1 where object_id=30                                   1hdyqyxhtavqs                                          1         1 INVALID_UNAUTH

从上面的输出可以看出,对表s1做DDL操作后缓存在Shared Pool里的执行计划没有被清除,但是两个SQL对应的执行计划状态都变为了"INVALID_UNAUTH",当再次执行SQL时会做硬解析,重新缓存解析树和执行计划。

3、dbms_shared_pool.purge包

它是从Oracle 10.2.0.4开始引入的一种方法,它可以用来删除指定的缓存在库缓存中的Shared Cursor,其影响范围公限于目标SQL所对应的Shared Cursor,也就是说它可以做到让Oracle在执行目标SQL时使用硬解析,在执行其他所有SQL时都和原来一样保持不变。

zx@MYDB>alter system flush shared_pool;System altered.zx@MYDB>select object_name from s1 where object_id=20;OBJECT_NAME------------------------------ICOL$zx@MYDB>select object_name from s1 where object_id=30;OBJECT_NAME------------------------------I_COBJ#zx@MYDB>select sql_text,sql_id,version_count,executions,OBJECT_STATUS,address,hash_value from v$sqlarea where sql_text like 'select object_name from s%';SQL_TEXT                                                     SQL_ID                                 VERSION_COUNT EXECUTIONS OBJECT_STATUS   ADDRESS        HASH_VALUE------------------------------------------------------------ --------------------------------------- ------------- ---------- --------------- ---------------- ----------select object_name from s1 where object_id=20               1s45nwjtws2tj                                      1     1 VALID          00000000B4F85A18 1942752049select object_name from s1 where object_id=30               1hdyqyxhtavqs                                      1     1 VALID          00000000BE7E56C8 1637183192

现在要删除object_id=20对应的SQL缓存的执行计划和解析树。

zx@MYDB>exec sys.dbms_shared_pool.purge('00000000B4F85A18,1942752049','C');PL/SQL procedure successfully completed.zx@MYDB>select sql_text,sql_id,version_count,executions,OBJECT_STATUS,address,hash_value from v$sqlarea where sql_text like 'select object_name from s%';SQL_TEXT                                                     SQL_ID                                 VERSION_COUNT EXECUTIONS OBJECT_STATUS   ADDRESS        HASH_VALUE------------------------------------------------------------ --------------------------------------- ------------- ---------- --------------- ---------------- ----------select object_name from s1 where object_id=30               1hdyqyxhtavqs                                      1     1 VALID          00000000BE7E56C8 1637183192

从输出可以看出object_id=20对应的SQL缓存的执行计划和解析树被删除了,而object_id=30对应的SQL的执行计划没有受影响。

需要注意的是,如果在10.2.0.4中使用dbms_shared_pool.purge,则在使用之前必须特工设置event 5614566(alter session set events '5614566 trace name context forever'),否则dbms_shared_pool.purge将不起作用,这个限制在10.2.0.4以上的版本中已经不存在了。如果默认没有安装dbms_shared_pool包的可以执行@?/rdbms/admin/dbmspool.sql


参考《基于Oracle的SQL优化》

官方文档:http://docs.oracle.com/cd/E11882_01/appdev.112/e40758/d_shared_pool.htm#ARPLS68077


缓存 再次 影响 查询 两个 方法 系统 输出 命令 数据 范围 语句 应用系统 情况 目标 应用 不同 不好 也就是 也就是说 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网金融科技 博彦科技互联网金融 互联网科技公司华为 中国 科技 互联网 智网互联网科技 卓越科技(互联网 ) 镁科技互联网资讯平台 常德市电业局互联网科技部 科技互联网大厂 武汉健翔互联网络科技有限公司 知域互联网科技有限公司大骗子 亳州好赞互联网科技有限公司 互联网行业科技股 高科技互联网发展前景如何 阿里互联网科技企业 高科技互联网套路 广州百诚互联网科技有限公司官网 互联网科技年终奖 有人说阿里系是互联网科技企业 科技和互联网行业的特点 嘟嘟瓜互联网科技 互联网科技实习生岗位职责 互联网媒体平台算高科技产业 华中科技大学互联网的牛人 合肥互联网科技公司公章图片 元气玛特互联网科技公司是外包吗 互联网硬科技公司 昆明中奇联合互联网科技 知域互联网科技有限公司官网 广州全民伙伴互联网科技有限公司
0