使用减号 oracle 优化插入查询
Posted
技术标签:
【中文标题】使用减号 oracle 优化插入查询【英文标题】:optimize Insert query with minus oracle 【发布时间】:2017-05-27 15:47:39 【问题描述】:想要优化需要更长时间才能完成的重要语句。
这个过程基本上会:
1) 在 NG_ORGANIZATION_CATEGORY_GTMP 上插入数据 5 个插入,一个一个。这些 DML 使用每个查询需要 10 秒。从最后的跟踪中,这些 DML 插入了以下行数:
Insert 1 - 292770
Insert 2 - 106648
Insert 3 - 67358
Insert 4 - 47775
Insert 5 - 6147
2) 运行有问题的查询,仅在表 NG_ORGANIZATION_CATEGORY 上插入大约 6 行(该表大约有 414k 行)。
INSERT INTO NG_ORGANIZATION_CATEGORY(ORGANIZATION_ID,CATEGORY_CODE,ADDED_DATE)
SELECT ORGANIZATION_ID,CATEGORY_CODE,:B1 AS ADDED_DATE
FROM NG_ORGANIZATION_CATEGORY_GTMP
WHERE (ORGANIZATION_ID,CATEGORY_CODE) IN (
SELECT ORGANIZATION_ID,CATEGORY_CODE
FROM NG_ORGANIZATION_CATEGORY_GTMP
MINUS
SELECT ORGANIZATION_ID,CATEGORY_CODE
FROM NG_ORGANIZATION_CATEGORY );
3) 处理从 NG_ORGANIZATION_CATEGORY 表中删除数据。也不错。
DELETE FROM NG_ORGANIZATION_CATEGORY
WHERE
(ORGANIZATION_ID,CATEGORY_CODE) IN ( SELECT ORGANIZATION_ID,CATEGORY_CODE
FROM NG_ORGANIZATION_CATEGORY MINUS SELECT ORGANIZATION_ID,CATEGORY_CODE
FROM NG_ORGANIZATION_CATEGORY_GTMP );
下面是有问题的插入的跟踪:
SQL ID: gwxs083gcfdd2 Plan Hash: 2436575860
INSERT INTO NG_ORGANIZATION_CATEGORY(ORGANIZATION_ID,CATEGORY_CODE,ADDED_DATE)
SELECT ORGANIZATION_ID,CATEGORY_CODE,:B1 AS ADDED_DATE FROM
NG_ORGANIZATION_CATEGORY_GTMP WHERE (ORGANIZATION_ID,CATEGORY_CODE) IN (
SELECT ORGANIZATION_ID,CATEGORY_CODE FROM NG_ORGANIZATION_CATEGORY_GTMP
MINUS SELECT ORGANIZATION_ID,CATEGORY_CODE FROM NG_ORGANIZATION_CATEGORY )
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 6704.07 6705.98 2 424814954 25 6
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 6704.07 6705.98 2 424814954 25 6
Misses in library cache during parse: 1
Misses in library cache during execute: 1
Optimizer mode: ALL_ROWS
Parsing user id: 146 (recursive depth: 1)
Number of plan statistics captured: 1
Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
0 0 0 LOAD TABLE CONVENTIONAL (cr=424814954 pr=2 pw=0 time=923492126 us)
6 6 6 FILTER (cr=424814953 pr=0 pw=0 time=1667461141 us)
414050 414050 414050 TABLE ACCESS FULL NG_ORGANIZATION_CATEGORY_GTMP (cr=1023 pr=0 pw=0 time=121231 us cost=2 size=35 card=1)
6 6 6 MINUS (cr=424813930 pr=0 pw=0 time=2409881660 us)
414050 414050 414050 SORT UNIQUE NOSORT (cr=423573150 pr=0 pw=0 time=2406932080 us cost=3 size=35 card=1)
414050 414050 414050 TABLE ACCESS FULL NG_ORGANIZATION_CATEGORY_GTMP (cr=423573150 pr=0 pw=0 time=2406112290 us cost=2 size=35 card=1)
414044 414044 414044 INDEX UNIQUE SCAN NG_ORG_CATEGORY_PK (cr=1240780 pr=0 pw=0 time=2134347 us cost=2 size=11 card=1)(object id 108100)
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
gc cr grant 2-way 1 0.00 0.00
db file sequential read 2 0.13 0.13
gc current grant 2-way 6 0.00 0.00
********************************************************************************
能否请您帮助我并告诉我如何调整此查询?我正在考虑添加一个并行提示,但由于查询中的减号,它将被忽略。
如果您有任何想法以及需要任何其他信息,请告诉我。
感谢您对它的关注。
提前致谢,
会
【问题讨论】:
【参考方案1】:你可以使用内连接代替 where ( ) IN
INSERT INTO NG_ORGANIZATION_CATEGORY(ORGANIZATION_ID,CATEGORY_CODE,ADDED_DATE)
SELECT ORGANIZATION_ID,CATEGORY_CODE,:B1
FROM NG_ORGANIZATION_CATEGORY_GTMP
INNER JOIN (
SELECT ORGANIZATION_ID,CATEGORY_CODE
FROM NG_ORGANIZATION_CATEGORY_GTMP
MINUS
SELECT ORGANIZATION_ID,CATEGORY_CODE
FROM NG_ORGANIZATION_CATEGORY
) T1 on NG_ORGANIZATION_CATEGORY_GTMP.ORGANIZATION_ID = T1.ORGANIZATION_ID
and NG_ORGANIZATION_CATEGORY_GTMP.CATEGORY_CODE = T1.CATEGORY_CODE
还有一个简单的提示去掉别名表单选择(没用)
【讨论】:
嗨@scaisEdge...我在不到 1 秒的时间内工作并跑了!我只需要确认数据,但我在插入之前运行了一个计数 MINUS,它插入了相同的数据计数。我将在星期一与开发人员核实,然后回到这篇文章!现在,非常感谢,你是男人!【参考方案2】:根据您的查询,您希望仅当类别表中不存在数据时才将数据插入到 gtmp 表中。 您可以尝试以下查询:
INSERT INTO NG_ORGANIZATION_CATEGORY(ORGANIZATION_ID,CATEGORY_CODE,ADDED_DATE)
SELECT ORGANIZATION_ID,CATEGORY_CODE,:B1 AS ADDED_DATE FROM
NG_ORGANIZATION_CATEGORY_GTMP T1 WHERE NOT EXISTS (
SELECT 1 FROM NG_ORGANIZATION_CATEGORY T2 WHERE T1.ORGANIZATION_ID=T2.ORGANIZATION_ID AND T1.CATEGORY_CODE=T2.CATEGORY_CODE);
【讨论】:
【参考方案3】:您可以使用 MERGE 语句仅使用源表中不存在的行填充目标表:
merge into ng_organization_category noc
using ( select distinct organization_id,
category_code
from ng_organization_category_gtmp ) gtmp
on ( gtmp.organization_id = noc.organization_id
and gtmp.category_code = noc.category_code )
when not matched then
insert (organization_id, category_code, added_date)
values (gtmp.organization_id, gtmp.category_code, :B1)
/
USING 子查询中的 DISTINCT 可能不是必需的,这取决于您的源数据。 (如果 GTMP 表有 (organization_id, category_code)
的多个实例,您现有的 INSERT 语句将插入它们,所以可能没关系。)
【讨论】:
嗨@APC..感谢您的帮助!我会等到 DEV 验证 scaisEdge 提供的建议,如果它没有用。我会尝试你的指示!非常感谢您的帮助。以上是关于使用减号 oracle 优化插入查询的主要内容,如果未能解决你的问题,请参考以下文章