我有一个表和一个访问该表的查询(在PL / SQL包中)。统计数据通常每周收集一次。
在表上运行了大量更新,导致特定索引列上的数据分布明显不同。 Oracle使用的查询计划(我可以从v$sqlarea
看到)是次优的。如果我从SQL * Plus中获取相同*查询的explain plan
,则返回一个好的计划。
我已收集了该表的统计数据。 Oracle仍在使用它最初提出的查询计划。 v$sqlarea.last_load_time
表明这是在统计数据生成之前生成的计划。我认为重新生成统计信息会使SQL缓存中的计划无效。
有没有办法从SQL缓存中删除这个语句?
(*不是字符字符,在SQL缓存中匹配相同,但语句相同)。
答案 0 :(得分:5)
如果您使用的是10.2.0.4或更高版本,则应该能够将DBMS_SHARED_POOL包用于purge a single cursor from the shared pool。
答案 1 :(得分:1)
我发现(在研究其他事情时)我应该做的就是使用
no_invalidate => FALSE
通过致电gather_table_stats
收集统计数据。这会导致引用该表的所有SQL计划立即失效。
Does not invalidate the dependent cursors if set to TRUE. The procedure
invalidates the dependent cursors immediately if set to FALSE. Use
DBMS_STATS.AUTO_INVALIDATE. to have Oracle decide when to invalidate dependent
cursors. This is the default.
默认值AUTO_INVALIDATE
似乎会在接下来的5个小时内导致SQL语句失效。如果要收集大量对象的统计信息,这是为了阻止大量的硬解析。