如何解决如果我截断了表,Oracle是否会再次进行硬解析?
如果我删除了表中的大多数行,或者我将其截断了,即使之前是软解析,它是否也可以再次进行硬解析?我很困惑,因为统计信息会更改,但查询不会更改。 此外,如果我截断该表并再次使用相同的数据填充它,是否会进行硬解析? (查询在所有情况下都是相同的)
解决方法
该解析对任何dml活动一无所知。您可以在文档中阅读所有内容。 SQL处理概述:https://docs.oracle.com/database/121/TGSQL/tgsql_sqlproc.htm#TGSQL178
共享池检查(解析的最后阶段,确定硬对软的位置:https://docs.oracle.com/database/121/TGSQL/tgsql_sqlproc.htm#GUID-BFF0B26C-0A5D-4F79-B01E-8E1C4064A6AD
,截断将导致额外的硬解析,而删除则不会。
为什么有区别?
truncate命令不仅会删除所有行,而且实际上会破坏并重新创建表。截断可能会使依赖索引无效,创建新的段并更改DBA_OBJECTS.DATA_OBJECT_ID
。引用被截断的表的任何语句将立即失效。
删除可能不是很危险,并且不会直接使引用该表的语句无效。随着时间的推移,如果有足够的删除,自动优化器统计信息作业将检测到已发生重大更改,并将重新收集表中的统计信息并使相关查询无效。但是,即使这种失效也可能不会立即发生,因为统计信息收集并不总是会使所有相关查询失效。
测试用例
要确定,我们可以测量硬解析的数量。下面的测试案例演示了截断会生成硬解析,而删除不会生成硬解析。 (但是出于某些无法解释的原因,可能会发生硬解析,例如,从共享池中删除了一个查询。因此,不要指望数字是准确的。)
首先,创建一个表以保存将要删除的行,并创建一个函数以获取当前会话中的硬解析次数。
create table test1(a number);
insert into test1 select level from dual connect by level <= 100000;
commit;
create or replace function get_hard_parse_count return number authid current_user is
v_value number;
begin
execute immediate
q'[
select value
from v$mystat
join v$statname
on v$mystat.statistic# = v$statname.statistic#
where name = 'parse count (hard)'
]'
into v_value;
return v_value;
end;
/
以下代码删除所有行并计数行,重复100次。但是硬解析的数量几乎没有增加。
--Count before: 751
select get_hard_parse_count from dual;
declare
v_count number;
begin
for i in 1 .. 100 loop
execute immediate 'delete from test1';
rollback;
execute immediate 'select count(*) from test1';
end loop;
end;
/
--Count after: 759
select get_hard_parse_count from dual;
下面的代码将截断而不是删除,并且硬解析的数量大量增加:
--Count before: 760
select get_hard_parse_count from dual;
declare
v_count number;
begin
for i in 1 .. 100 loop
execute immediate 'truncate table test1';
rollback;
execute immediate 'select count(*) from test1';
end loop;
end;
/
--Count after: 1,162
select get_hard_parse_count from dual;
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。