Oracle 12c性能调优 - 针对全局临时表

时间:2018-01-12 02:24:09

标签: oracle12c sql-tuning

Oracle Performance Gurus,

我的任务是调整一个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(分别为撤销和临时表空间扩展错误)。过去几周我们一直在增加我们的临时空间,以暂时缓解错误。我在这里添加表空间信息 -

  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的一些功能,所以不知道如何在这张桌子上列出很多会话级统计数据。

谢谢, 布伦登

2 个答案:

答案 0 :(得分:2)

我会改变方法。您可以编写查询以保留所需的行,而不是删除您不想要的行。将它们写入新表。然后删除旧表并重命名。所以基本上你有一些逻辑上的东西

  1. 插入T1_new 选择......其中DUP = 1

  2. drop table T1

  3. 将T1_new重命名为T1

  4. 这也开启了使用直接路径插入的机会(通过/ * + APPEND * / hint)。如果您有可用资源,也可以使用并行性。

答案 1 :(得分:1)

  1. 将FLAG1添加到索引。将索引更改为CREATE INDEX T1IDX ON T1 ("A", "B", "C", "D", "FLAG1");将允许DELETE语句像使用瘦表一样使用索引。计划应更改为使用INDEX FULL SCANINDEX FAST FULL SCAN
  2. 使用临时撤消。 Oracle 12c允许将UNDO信息存储在临时表的表空间中,从而减少UNDO和REDO的生成。要启用此功能,请运行ALTER SESSION SET TEMP_UNDO_ENABLED = TRUE;之类的命令。 (但要小心先创建一个新会话。如果你的会话之前使用过一个临时表,那么该命令将无声地失败。)我对你的对象的小数据测试只显示了7%的性能提升,但它是一个容易改变,没有任何缺点。