Если я удалю большую часть строк в таблице или обрежу ее, будет ли она снова подвергнута жесткому синтаксическому анализу, даже если раньше это был мягкий синтаксический анализ? Я запутался, потому что статистика изменится, а запрос не изменится. Кроме того, идет ли жесткий синтаксический анализ, если я усекаю таблицу и снова заполняю ее теми же данными? (Запрос во всех случаях одинаковый)

1
oramas 19 Авг 2020 в 13:36

2 ответа

Лучший ответ

Усечение приведет к дополнительному жесткому синтаксическому анализу, а удаление - нет.

Почему разница?

Команда усечения не только удаляет все строки, но и фактически уничтожает и воссоздает таблицу. Усечение может сделать зависимые индексы недействительными, создать новые сегменты и изменить 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
Jon Heller 20 Авг 2020 в 04:59

Парсинг ничего не знает ни о какой активности 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

1
EdStevens 19 Авг 2020 в 12:14