Настройка производительности Oracle 12c — удаление запроса к глобальной временной таблице

Гуру производительности Oracle,

У меня есть задача настроить зверя sql, который иногда работает более 18 часов в зависимости от количества строк, которые он пытается удалить из глобальной временной таблицы. Для таблицы определен индекс, но вместо этого оптимизатор выполняет хеш-соединение — вот подробности таблицы и результаты плана объяснения таблицы —

    DELETE FROM 
       T1
    WHERE ROWID IN
    (
        SELECT ROWID FROM 
        (
            SELECT 
              ROWID,
              ROW_NUMBER() OVER (PARTITION BY A,B,C,D ORDER BY C,D) DUP
              FROM T1
              WHERE FLAG1 = 0
        )
        WHERE DUP > 1
    );

  COMMIT;

Определение таблицы приведено здесь:

CREATE GLOBAL TEMPORARY TABLE "T1"      
   (    
A   VARCHAR2(50 BYTE), 
B   NUMBER(10,0), 
C   VARCHAR2(20 BYTE), 
D   NUMBER, 
A1  FLOAT(126), 
B1  FLOAT(126), 
C1  FLOAT(126), 
D1  FLOAT(126), 
A2  NUMBER, 
B2  NUMBER, 
C2  FLOAT(126), 
D2  FLOAT(126), 
A3  FLOAT(126), 
B3  FLOAT(126), 
C3  FLOAT(126), 
D3  FLOAT(126), 
A4  FLOAT(126), 
B4  FLOAT(126), 
FLAG1   NUMBER
) ON COMMIT PRESERVE ROWS ;     
CREATE INDEX T1IDX ON T1 ("A", "B", "C", "D") ; 

Результаты плана объяснения:

Query Plan                                 Rows        Rowsource Time
DELETE STATEMENT   Cost = 3936614
DELETE  T1                                              1109
       NESTED LOOPS                         1           1
         VIEW  VW_NSO_1                     220M        0
           SORT UNIQUE                      1           163
             VIEW                           220M        2
               WINDOW SORT                  220M        355
                 TABLE ACCESS FULL T1       220M        94
  TABLE ACCESS BY USER ROWID T1             1           313

Также важно отметить, что мы также иногда получаем ORA-01652 и ORA-30036 (ошибки расширения табличного пространства Undo и Temp соответственно), когда вышеуказанный запрос выполняется дольше, чем обычно. В течение последних нескольких недель мы расширяли наше временное пространство, чтобы временно устранить ошибки. Я добавляю информацию о табличном пространстве здесь -

  Tablespace Name               SizeinMB        FreeMB
  ----------------              ---------       --------
  T1_Sp1_DATA_TS                 3712           180.88
  T1_PE1_INDEX_TS                1              0.94
  SYSAUX                         1160           60.06
  T1_SYS_BLOB_TS                 525            81.13
  T1_SIF_EXPORT_TS               5              4
  T1_SIF_TS                      1              0.69
  T1_FL1_INDEX_TS                3590           173.06
  Staging_DATA_TS                1436           165.63
  T1_FLR_pf1_TS                  2219           238
  T1_Sp1_dv1_TS                  1004           2.75
  T1_Sp1_pf1_TS                  5868           8.75
  T1_SYS_DATA_TS                 34             3.63
  T1_SYS_el1_TS                  159            11.88
  T1_Sp1_INDEX_TS                5785           309.69
  T1_e1_INDEX_TS                 5              4
  USERS                          66740          21538.06
  T1_FL1_DATA_TS                 1932           95.38
  T1_BLOB_TS                     12415          591.44
  T1_Sp1_Fx1_TS                  3249           215.75
  T1_ST1_INDEX_TS                2              0.94
  T1_SIF_INDEX_TS                2              0.38
  SYSTEM                         405            7.19
  T1_FL1_Fx1_TS                  6475           351.63
  T1_ST1_DATA_TS                 1              0.13
  T1_SA_INDEX_TS                 5              4
  T1_NET_DATA_TS                 13             0.19
  T1_Staging_DATA_TS             872404.9375    176406.69
  T1_FL1_sc1_TS                  4071           254.63
  T1_SA_DATA_TS                  5              4
  T1_NET_BLOB_TS                 26757          1291.38
  T1_NET_INDEX_TS                57             3.63
  T1_SYS_INDEX_TS                33             4.88
  T1_Sp1_ps1_TS                  2129           103.75
  T1_e1_DATA_TS                  5              4
  T1_SA_BLOB_TS                  5              4
  T1_SI1_BLOB_TS                 2              0.25
  T1_PE1_DATA_TS                 1              0.94
  TEMP                           196605.96875   

Мне интересно, как лучше всего настроить запрос, чтобы он выполнялся быстрее - я собираюсь попытаться принудительно удалить индексированную подсказку или подсказку NLJ, чтобы посмотреть, поможет ли это, но если у кого-то из вас есть идеи получше , я был бы очень признателен за это.

Это Oracle 12c, и у нас есть статистика на уровне сеанса для всех наших глобальных временных таблиц. Я все еще изучаю некоторые функции 12c, поэтому не уверен, что делать с большей частью статистики на уровне сеанса в этой таблице.

Спасибо, Брендон.


person Brendon    schedule 12.01.2018    source источник


Ответы (2)


Я бы изменил подход. Вместо того, чтобы удалять ненужные строки, напишите запрос, чтобы сохранить нужные строки. Запишите их в новую таблицу. Затем удалите старую таблицу и переименуйте. Итак, в основном у вас есть что-то логически похожее на

  1. вставить в T1_new select .... где DUP = 1

  2. падающий стол T1

  3. переименовать T1_new в T1

Это также открывает возможность использовать прямую вставку пути (через подсказку /*+APPEND */). Если у вас есть доступные ресурсы, вы также можете использовать параллелизм.

person BobC    schedule 12.01.2018
comment
Спасибо, Боб. Я обязательно попробую этот подход и отпишусь о результатах. Наши любимые администраторы баз данных говорят нам не использовать более 2 потоков DOP, хотя я вижу, что для parallel_max_servers установлено значение 320 с cpu_count 8 и parallel_threads_per_cpu равным 2. Возможно, из-за того, что это глобальные временные таблицы, нам рекомендуется использовать dop. из 2. Кстати, можем ли мы одновременно использовать подсказку добавления вставки вместе с DOP из 2? - person Brendon; 12.01.2018
comment
Какая у вас аппаратная платформа? Тот факт, что это GTT, не должен иметь отношения к решению DOP. Несмотря на это, даже последовательно, используя вставку прямого пути, вы должны быть на порядки быстрее. - person BobC; 12.01.2018
comment
x86_64/Линукс 2.4.xx. Я также читаю больше о статистике по GTT из блогов Тома и ломаю голову… как мы можем сказать CBO автоматически проводить динамическую выборку, поскольку это GTT? Я уверен, что есть параметр .. - person Brendon; 12.01.2018
comment
Для parallel_threads_per_cpu, вероятно, следует установить значение 1. Но в данном контексте это не имеет никакого значения. - person BobC; 12.01.2018
comment
Динамический сэмплинг происходит автоматически, если вы его не отключили. Каковы ваши настройки для оптимизатора_динамики_сэмплинга? - person BobC; 12.01.2018
comment
optimizer_dynamic_sampling имеет значение 2. - person Brendon; 12.01.2018
comment
Я не думаю, что добавление/изменение индексов — лучший подход. Если статистика верна, вы пытаетесь удалить 220 миллионов строк. Вы уже пробовали подход переопределения, который я предложил? - person BobC; 14.01.2018
comment
Да, я изменил подход, сделав это в 3 этапа, как вы упомянули, а также установил Temp_Undo_Enabled=True в коде и сократил время выполнения за гораздо меньшее время, от 40 минут до менее часа. Спасибо за ваше предложение. - person Brendon; 14.01.2018
comment
Если вы используете подсказку APPEND, вам не нужна отмена, поэтому вам не нужно устанавливать temp_undo_enabled - person BobC; 14.01.2018

  1. Добавьте FLAG1 к индексу. Изменение индекса на CREATE INDEX T1IDX ON T1 ("A", "B", "C", "D", "FLAG1"); позволит оператору DELETE использовать индекс как тощую таблицу. Планы должны измениться, чтобы использовать либо INDEX FULL SCAN, либо INDEX FAST FULL SCAN.
  2. Используйте временную отмену. Oracle 12c позволяет хранить информацию UNDO внутри табличного пространства временной таблицы, уменьшая количество UNDO и REDO. Чтобы включить эту функцию, запустите команду, например ALTER SESSION SET TEMP_UNDO_ENABLED = TRUE;. (Но будьте осторожны, чтобы сначала создать новый сеанс. Если в вашем сеансе ранее использовалась временная таблица, эта команда автоматически завершится ошибкой.) Мои тесты с небольшими данными с вашими объектами показали улучшение производительности только на 7%, но это легкое изменение без недостаток.
person Jon Heller    schedule 12.01.2018
comment
Спасибо, Джон. Я попробую установить для параметра temp_undo_enabled значение True и опубликую результаты. Этот код часто выдает как Ora-16052, так и Ora-30036 об ошибке при расширении расширения временного сегмента и табличного пространства отмены соответственно. Я собираюсь отредактировать свой исходный пост выше и добавить информацию об используемом табличном пространстве и свободной информации. - person Brendon; 12.01.2018
comment
Я добавил в свой код ALTER SESSION SET TEMP_UNDO_ENABLED = TRUE, а также изменил подход к удалению из одной таблицы, и теперь код выполняется менее чем за час. Приятно узнать об опции Temp_Undo_Enabled и спасибо за вашу помощь! - person Brendon; 14.01.2018