有朋友问我一个update语句,下面两种写法哪个性能更高,一个是没HINT的,一个是有HINT的
UPDATE CS_PERFORMANCE_CURRENT C SET C.PERFORMANCE_SCORE = '0.00', C.ASSESS_DESC = '劳动纪律考核' WHERE C.TARGET_MODE_SEQ_ID = (SELECT D.SEQ_ID FROM CS_TARGET_MODEL_REL D, CS_AREA A WHERE D.ASSESS_ID = 1265 AND C.TARGET_MODE_SEQ_ID = D.SEQ_ID AND D.STAFF_ID = 8 AND C.COM_DATE = TO_DATE('20110801','YYYYMMDD') AND D.TARGET_MODEL_ID = 332 AND D.STATE = TO_CHAR(2) AND D.AREA_ID = A.AREA_ID AND A.AREA_NAME = '永兴支局'); Plan hash value: 2321634139 ---------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------------------------- | 0 | UPDATE STATEMENT | | 1 | 41 | 679 (1)| 00:00:09 | | 1 | UPDATE | CS_PERFORMANCE_CURRENT | | | | | |* 2 | FILTER | | | | | | | 3 | TABLE ACCESS FULL | CS_PERFORMANCE_CURRENT | 124K| 4968K| 664 (1)| 00:00:08 | |* 4 | FILTER | | | | | | | 5 | NESTED LOOPS | | 1 | 52 | 3 (0)| 00:00:01 | |* 6 | TABLE ACCESS BY INDEX ROWID| CS_TARGET_MODEL_REL | 1 | 26 | 2 (0)| 00:00:01 | |* 7 | INDEX UNIQUE SCAN | PK_CS_TARGET_RULE_REL | 1 | | 1 (0)| 00:00:01 | |* 8 | TABLE ACCESS BY INDEX ROWID| CS_AREA | 1 | 26 | 1 (0)| 00:00:01 | |* 9 | INDEX UNIQUE SCAN | PK_CS_AREA_NEW | 1 | | 0 (0)| 00:00:01 | ---------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("C"."TARGET_MODE_SEQ_ID"= (SELECT "D"."SEQ_ID" FROM "CS_AREA" "A","CS_TARGET_MODEL_REL" "D" WHERE :B1=TO_DATE(' 2011-08-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "D"."SEQ_ID"=:B2 AND "D"."STAFF_ID"=8 AND "D"."ASSESS_ID"=1265 AND "D"."TARGET_MODEL_ID"=332 AND "D"."STATE"='2' AND "D"."AREA_ID"="A"."AREA_ID" AND "A"."AREA_NAME"='永兴支局')) 4 - filter(:B1=TO_DATE(' 2011-08-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss')) 6 - filter("D"."STAFF_ID"=8 AND "D"."ASSESS_ID"=1265 AND "D"."TARGET_MODEL_ID"=332 AND "D"."STATE"='2') 7 - access("D"."SEQ_ID"=:B1) 8 - filter("A"."AREA_NAME"='永兴支局') 9 - access("D"."AREA_ID"="A"."AREA_ID") 已用时间: 00: 00: 00.29 统计信息 ---------------------------------------------------------- 1 recursive calls 0 db block gets 32670 consistent gets 21 physical reads 0 redo size 536 bytes sent via SQL*Net to client 978 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 0 rows processed
UPDATE /*+ PUSH_SUBQ(@D) */CS_PERFORMANCE_CURRENT C SET C.PERFORMANCE_SCORE = '0.00', C.ASSESS_DESC = '劳动纪律考核' WHERE C.TARGET_MODE_SEQ_ID = (SELECT /*+ QB_NAME(D) */ D.SEQ_ID FROM CS_TARGET_MODEL_REL D, CS_AREA A WHERE D.ASSESS_ID = 1265 AND C.TARGET_MODE_SEQ_ID = D.SEQ_ID AND D.STAFF_ID = 8 AND C.COM_DATE = TO_DATE('20110801','YYYYMMDD') AND D.TARGET_MODEL_ID = 332 AND D.STATE = TO_CHAR(2) AND D.AREA_ID = A.AREA_ID AND A.AREA_NAME = '永兴支局') Plan hash value: 4189652906 ---------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------------------------- | 0 | UPDATE STATEMENT | | 1 | 39 | 43 (0)| 00:00:01 | | 1 | UPDATE | CS_PERFORMANCE_CURRENT | | | | | |* 2 | TABLE ACCESS FULL | CS_PERFORMANCE_CURRENT | 1 | 39 | 40 (0)| 00:00:01 | |* 3 | FILTER | | | | | | | 4 | NESTED LOOPS | | 1 | 47 | 3 (0)| 00:00:01 | |* 5 | TABLE ACCESS BY INDEX ROWID| CS_TARGET_MODEL_REL | 1 | 25 | 2 (0)| 00:00:01 | |* 6 | INDEX UNIQUE SCAN | PK_CS_TARGET_RULE_REL | 1 | | 1 (0)| 00:00:01 | |* 7 | TABLE ACCESS BY INDEX ROWID| CS_AREA | 1 | 22 | 1 (0)| 00:00:01 | |* 8 | INDEX UNIQUE SCAN | PK_CS_AREA_NEW | 1 | | 0 (0)| 00:00:01 | ---------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("C"."TARGET_MODE_SEQ_ID"= (SELECT /*+ PUSH_SUBQ QB_NAME ("D") */ "D"."SEQ_ID" FROM "CS_AREA" "A","CS_TARGET_MODEL_REL" "D" WHERE :B1=TO_DATE(' 2011-08-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "D"."SEQ_ID"=:B2 AND "D"."ASSESS_ID"=1265 AND "D"."STAFF_ID"=8 AND "D"."TARGET_MODEL_ID"=332 AND "D"."STATE"='2' AND "D"."AREA_ID"="A"."AREA_ID" AND "A"."AREA_NAME"='永兴支局')) 3 - filter(:B1=TO_DATE(' 2011-08-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss')) 5 - filter("D"."ASSESS_ID"=1265 AND "D"."STAFF_ID"=8 AND "D"."TARGET_MODEL_ID"=332 AND "D"."STATE"='2') 6 - access("D"."SEQ_ID"=:B1) 7 - filter("A"."AREA_NAME"='永兴支局') 8 - access("D"."AREA_ID"="A"."AREA_ID") 统计信息 ---------------------------------------------------------- 1 recursive calls 0 db block gets 32670 consistent gets 21 physical reads 0 redo size 536 bytes sent via SQL*Net to client 978 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 0 rows processed
可以看到,逻辑读都是一样的,那么这个SQL,加不加HINT性能都一样。其实对于Oracle中的update 语句,如果SQL很复杂,需要关联多个表去做update,这个时候应该用
merge 语句代替 update,用Merge 改写之后 :
MERGE INTO CS_PERFORMANCE_CURRENT A USING (SELECT D.SEQ_ID FROM CS_TARGET_MODEL_REL D, CS_AREA M WHERE D.ASSESS_ID = 1265 AND D.STAFF_ID = 8 AND D.TARGET_MODEL_ID = 332 AND D.STATE = TO_CHAR(2) AND D.AREA_ID = M.AREA_ID AND M.AREA_NAME = '永兴支局') H ON (A.TARGET_MODE_SEQ_ID = H.SEQ_ID) WHEN MATCHED THEN UPDATE SET A.PERFORMANCE_SCORE = '0.00', A.ASSESS_DESC = '劳动纪律考核' WHERE A.COM_DATE = TO_DATE('20110801', 'YYYYMMDD'); ---------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------------------------- | 0 | MERGE STATEMENT | | 1 | 167 | 750 (1)| 00:00:10 | | 1 | MERGE | CS_PERFORMANCE_CURRENT | | | | | | 2 | VIEW | | | | | | |* 3 | HASH JOIN | | 1 | 210 | 750 (1)| 00:00:10 | | 4 | NESTED LOOPS | | 1 | 52 | 85 (2)| 00:00:02 | |* 5 | TABLE ACCESS FULL | CS_TARGET_MODEL_REL | 1 | 26 | 84 (2)| 00:00:02 | |* 6 | TABLE ACCESS BY INDEX ROWID| CS_AREA | 1 | 26 | 1 (0)| 00:00:01 | |* 7 | INDEX UNIQUE SCAN | PK_CS_AREA_NEW | 1 | | 0 (0)| 00:00:01 | | 8 | TABLE ACCESS FULL | CS_PERFORMANCE_CURRENT | 124K| 18M| 664 (1)| 00:00:08 | ---------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("A"."TARGET_MODE_SEQ_ID"="D"."SEQ_ID") 5 - filter("D"."STAFF_ID"=8 AND "D"."ASSESS_ID"=1265 AND "D"."TARGET_MODEL_ID"=332 AND "D"."STATE"='2') 6 - filter("M"."AREA_NAME"='永兴支局') 7 - access("D"."AREA_ID"="M"."AREA_ID") 统计信息 ---------------------------------------------------------- 333 recursive calls 0 db block gets 3474 consistent gets 3 physical reads 0 redo size 546 bytes sent via SQL*Net to client 998 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 15 sorts (memory) 0 sorts (disk) 0 rows processed
逻辑读下降了近10倍,这里 CS_PERFORMANCE_CURRENT 是全表扫描,它有100W的数据量,所以建立索引在TARGET_MODE_SEQ_ID列上
Plan hash value: 3908453434 ----------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ----------------------------------------------------------------------------------------------------------- | 0 | MERGE STATEMENT | | 1 | 167 | 88 (2)| 00:00:02 | | 1 | MERGE | CS_PERFORMANCE_CURRENT | | | | | | 2 | VIEW | | | | | | | 3 | TABLE ACCESS BY INDEX ROWID | CS_PERFORMANCE_CURRENT | 1 | 158 | 3 (0)| 00:00:01 | | 4 | NESTED LOOPS | | 1 | 210 | 88 (2)| 00:00:02 | | 5 | NESTED LOOPS | | 1 | 52 | 85 (2)| 00:00:02 | |* 6 | TABLE ACCESS FULL | CS_TARGET_MODEL_REL | 1 | 26 | 84 (2)| 00:00:02 | |* 7 | TABLE ACCESS BY INDEX ROWID| CS_AREA | 1 | 26 | 1 (0)| 00:00:01 | |* 8 | INDEX UNIQUE SCAN | PK_CS_AREA_NEW | 1 | | 0 (0)| 00:00:01 | |* 9 | INDEX RANGE SCAN | IDX_CS_PFC_CURRENT | 1 | | 1 (0)| 00:00:01 | ----------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 6 - filter("D"."STAFF_ID"=8 AND "D"."ASSESS_ID"=1265 AND "D"."TARGET_MODEL_ID"=332 AND "D"."STATE"='2') 7 - filter("M"."AREA_NAME"='永兴支局') 8 - access("D"."AREA_ID"="M"."AREA_ID") 9 - access("A"."TARGET_MODE_SEQ_ID"="D"."SEQ_ID") 已用时间: 00: 00: 00.18 统计信息 ---------------------------------------------------------- 0 recursive calls 0 db block gets 386 consistent gets 0 physical reads 0 redo size 544 bytes sent via SQL*Net to client 998 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 0 rows processed
现在逻辑读降低到386
在Oracle当中,强烈建议 =使用 merge 代替 update语句