如果我截断了表,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;

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...