【发布时间】:2020-12-08 14:42:41
【问题描述】:
如果我删除了表中的大部分行,或者我截断了它,是否会再次进行硬解析,即使之前是软解析?我很困惑,因为统计数据会改变,但查询不会改变。 此外,如果我截断表并用相同的数据再次填充它,它是否会进行硬解析? (查询在所有情况下都是一样的)
【问题讨论】:
标签: oracle database-performance database-administration sqlperformance sql-tuning
如果我删除了表中的大部分行,或者我截断了它,是否会再次进行硬解析,即使之前是软解析?我很困惑,因为统计数据会改变,但查询不会改变。 此外,如果我截断表并用相同的数据再次填充它,它是否会进行硬解析? (查询在所有情况下都是一样的)
【问题讨论】:
标签: oracle database-performance database-administration sqlperformance sql-tuning
截断会导致额外的硬解析,但删除不会。
截断命令不仅会删除所有行,它实际上会破坏并重新创建表。截断可能会使相关索引无效、创建新段并更改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;
【讨论】:
解析对任何 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
【讨论】: