我的查询如下
UPDATE CONVERTED T1
SET PARENTID = (SELECT MAX(ID) FROM
CONVERTED T2 WHERE T2.ID < T1.ID
AND T1.PREVOBJNUM = T2.OBID )
它需要几个小时才能运行,因为它们是100万条记录,并且必须为每一行执行一个子查询。有没有办法优化查询以更快地运行?
编辑:这是xplan
Plan hash value: 3177327108
----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1053K| 31M| 576M (1)|802:56:03 |
| 1 | UPDATE | CONVERTED | | | | |
| 2 | TABLE ACCESS FULL | CONVERTED | 1053K| 31M| 84276 (1)| 00:07:03 |
| 3 | SORT AGGREGATE | | 1 | 17 | | |
|* 4 | TABLE ACCESS BY INDEX ROWID| CONVERTED | 1 | 17 | 547 (1)| 00:00:03 |
|* 5 | INDEX RANGE SCAN | CONVERTED_PK | 9478 | | 22 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - filter("T2"."OBID"=:B1)
5 - access("T2"."ID"<:B1)
这里是表DLL
--------------------------------------------------------
-- DDL for Table CONVERTED
--------------------------------------------------------
CREATE TABLE "AMS"."CONVERTED"
( "ID" NUMBER(10,0),
"L1" VARCHAR2(255 CHAR),
"L1_DESC" VARCHAR2(255 CHAR),
"L2" VARCHAR2(255 CHAR),
"L2_DESC" VARCHAR2(255 CHAR),
"L3" VARCHAR2(255 CHAR),
"L3_DESC" VARCHAR2(255 CHAR),
"L4" VARCHAR2(255 CHAR),
"L4_DESC" VARCHAR2(255 CHAR),
"L5" VARCHAR2(255 CHAR),
"L5_DESC" VARCHAR2(255 CHAR),
"L6" VARCHAR2(255 CHAR),
"L6_DESC" VARCHAR2(255 CHAR),
"L7" VARCHAR2(255 CHAR),
"L7_DESC" VARCHAR2(255 CHAR),
"L8" VARCHAR2(255 CHAR),
"L8_DESC" VARCHAR2(255 CHAR),
"L9" VARCHAR2(255 CHAR),
"L9_DESC" VARCHAR2(255 CHAR),
"L10" VARCHAR2(255 CHAR),
"L10_DESC" VARCHAR2(255 CHAR),
"L11" VARCHAR2(255 CHAR),
"L11_DESC" VARCHAR2(255 CHAR),
"L12" VARCHAR2(255 CHAR),
"L12_DESC" VARCHAR2(255 CHAR),
"L13" VARCHAR2(255 CHAR),
"L13_DESC" VARCHAR2(255 CHAR),
"L14" VARCHAR2(255 CHAR),
"L14_DESC" VARCHAR2(255 CHAR),
"L15" VARCHAR2(255 CHAR),
"L15_DESC" VARCHAR2(255 CHAR),
"OBID" VARCHAR2(255 CHAR),
"OBDESC" VARCHAR2(255 CHAR),
"MATTYPE" VARCHAR2(255 CHAR),
"NUMOF" VARCHAR2(255 CHAR),
"UOM" VARCHAR2(255 CHAR),
"OBTYPE" VARCHAR2(255 CHAR),
"PREVOBJNUM" VARCHAR2(255 CHAR),
"PARENTID" NUMBER(10,0),
"POSITION" NUMBER(10,0),
"LEVEL_" NUMBER(10,0)
) SEGMENT CREATION IMMEDIATE
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
NOCOMPRESS LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "AMS_DATA" ;
--------------------------------------------------------
-- DDL for Index CONVERTED_PK
--------------------------------------------------------
CREATE UNIQUE INDEX "AMS"."CONVERTED_PK" ON "AMS"."CONVERTED" ("ID")
PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "AMS_DATA" ;
--------------------------------------------------------
-- Constraints for Table CONVERTED
--------------------------------------------------------
ALTER TABLE "AMS"."CONVERTED" ADD CONSTRAINT "CONVERTED_PK" PRIMARY KEY ("ID")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "AMS_DATA" ENABLE;
alter table "AMS"."CONVERTED" modify ("ID" not null enable);
以下是带有索引的xplan
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1448708152
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1053K| 31M| 4296K (25)| 05:59:18 |
| 1 | UPDATE | CONVERTED | | | | |
| 2 | TABLE ACCESS FULL | CONVERTED | 1053K| 31M| 84276 (1)| 00:07:03 |
| 3 | SORT AGGREGATE | | 1 | 17 | | |
| 4 | FIRST ROW | | 1 | 17 | 3 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN (MIN/MAX)| INDEX1 | 1 | 17 | 3 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
5 - access("T2"."OBID"=:B1 AND "T2"."ID"<:B2)
17 rows selected
答案 0 :(得分:1)
我会从(OBID,ID)上的索引开始,因为它会避免解释计划的ID 4上的表访问。
现有查询的大部分成本来自嵌套循环的1053K执行,其中每个循环执行成本547.在547中,22是使用索引访问表而525是用于访问表。必须访问该表才能查找指定OBID的行,其ID小于要更新的行的ID。通过在索引中包含ID,您可以执行子查询而无需访问该表,从而消除了每个嵌套循环执行525的成本。
查看具有该索引的执行计划会很有趣。现在访问索引的成本可能高于当前索引引用的22,但嵌套循环的总体成本将大大降低。
编辑:啊,嵌套循环执行现在非常有效。优化器不仅识别所有候选行,然后对它们进行排序以查找最大ID,它通过直接扫描索引来查找最大ID。好的。
答案 1 :(得分:0)
我建议使用PL / SQL程序,它结合了一些高级技术,如 BULK COLLECT , FORALL 语句和 PARALLEL 执行({{ 3}}将向您展示如何实施此类解决方案)。
Cyryl