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的一些功能,所以不知道如何在这张桌子上列出很多会话级统计数据。
谢谢, 布伦登
答案 0 :(得分:2)
我会改变方法。您可以编写查询以保留所需的行,而不是删除您不想要的行。将它们写入新表。然后删除旧表并重命名。所以基本上你有一些逻辑上的东西
插入T1_new 选择......其中DUP = 1
drop table T1
将T1_new重命名为T1
这也开启了使用直接路径插入的机会(通过/ * + APPEND * / hint)。如果您有可用资源,也可以使用并行性。
答案 1 :(得分:1)
CREATE INDEX T1IDX ON T1 ("A", "B", "C", "D", "FLAG1");
将允许DELETE语句像使用瘦表一样使用索引。计划应更改为使用INDEX FULL SCAN
或INDEX FAST FULL SCAN
。ALTER SESSION SET TEMP_UNDO_ENABLED = TRUE;
之类的命令。 (但要小心先创建一个新会话。如果你的会话之前使用过一个临时表,那么该命令将无声地失败。)我对你的对象的小数据测试只显示了7%的性能提升,但它是一个容易改变,没有任何缺点。