【问题标题】:Does Oracle go for hard parse again if I truncate the table?如果我截断表,Oracle 会再次进行硬解析吗?
【发布时间】:2020-12-08 14:42:41
【问题描述】:

如果我删除了表中的大部分行,或者我截断了它,是否会再次进行硬解析,即使之前是软解析?我很困惑,因为统计数据会改变,但查询不会改变。 此外,如果我截断表并用相同的数据再次填充它,它是否会进行硬解析? (查询在所有情况下都是一样的)

【问题讨论】:

    标签: oracle database-performance database-administration sqlperformance sql-tuning


    【解决方案1】:

    截断会导致额外的硬解析,但删除不会。

    为什么会有差异?

    截断命令不仅会删除所有行,它实际上会破坏并重新创建表。截断可能会使相关索引无效、创建新段并更改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;
    

    【讨论】:

      【解决方案2】:

      解析对任何 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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-09-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多