使用减号 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 优化插入查询的主要内容,如果未能解决你的问题,请参考以下文章

Oracle查询优化-插入更新与删除

SQL Oracle中的减号查询

Oracle SQL 查询优化.Part4

Oracle 减号查询。如果顶部 SQL 和底部 SQL 不包含 NULL,我如何获得带有 NULLS 的结果?

Oracle 查询调优建议

如何在 Oracle SQL Developer 中执行超过 100 万条插入查询?