一美女DBA想学SQL优化,经常和俺扯淡,俺也乐于扯淡。俺最喜欢美女了。今天他发来一个SQL叫俺帮忙看看。
执行计划如下:
SELECT "A1"."CODE", "A1"."DEVICE_ID", "A1"."SIDEB_PORT_ID", "A1"."VERSION" FROM (SELECT "A2"."CODE" "CODE", "A2"."DEVICE_ID" "DEVICE_ID", "A2"."SIDEB_PORT_ID" "SIDEB_PORT_ID", "A3"."VERSION" "VERSION", ROW_NUMBER() OVER(PARTITION BY "A4"."PROD_ID" ORDER BY "A4"."HIST_TIME" DESC) "RN" FROM "RM"."H_PROD_2_RF_SERV" "A4", "RM"."H_RSC_FACING_SERV_LINE_ITEM" "A3", "RM"."CONNECTOR" "A2" WHERE "A4"."SERV_ID" = "A3"."SERV_ID" AND "A3"."LINE_ID" = "A2"."CONNECTOR_ID" AND EXISTS (SELECT 0 FROM "RM"."DEVICE_ITEM" "A5" WHERE "A5"."DEVICE_ID" = "A2"."DEVICE_ID" AND "A5"."ITEM_SPEC_ID" = 200006 AND "A5"."VALUE" ='7') AND "A4"."PROD_ID" = 313) "A1" WHERE "A1"."RN" = 1 -----9.437秒 48194511行 A5 35467304行 A2 Execution Plan ---------------------------------------------------------- Plan hash value: 10111536 ----------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ----------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 175 | 20 (10)| 00:00:01 | |* 1 | VIEW | | 1 | 175 | 20 (10)| 00:00:01 | |* 2 | WINDOW SORT PUSHED RANK | | 1 | 109 | 20 (10)| 00:00:01 | | 3 | NESTED LOOPS | | 1 | 109 | 19 (6)| 00:00:01 | | 4 | NESTED LOOPS | | 1 | 80 | 17 (6)| 00:00:01 | | 5 | MERGE JOIN CARTESIAN | | 1 | 60 | 13 (8)| 00:00:01 | | 6 | SORT UNIQUE | | 1 | 36 | 6 (0)| 00:00:01 | |* 7 | TABLE ACCESS BY INDEX ROWID| DEVICE_ITEM | 1 | 36 | 6 (0)| 00:00:01 | |* 8 | INDEX RANGE SCAN | IDX_DEVICE_ITEM_VALE | 9 | | 4 (0)| 00:00:01 | | 9 | BUFFER SORT | | 4 | 96 | 7 (15)| 00:00:01 | | 10 | TABLE ACCESS BY INDEX ROWID| H_PROD_2_RF_SERV | 4 | 96 | 6 (0)| 00:00:01 | |* 11 | INDEX RANGE SCAN | IDX_HP2RS_PRODID_SERVID | 4 | | 2 (0)| 00:00:01 | | 12 | TABLE ACCESS BY INDEX ROWID | H_RSC_FACING_SERV_LINE_ITEM | 2 | 40 | 4 (0)| 00:00:01 | |* 13 | INDEX RANGE SCAN | IDX_HRFSLI_SERV | 2 | | 2 (0)| 00:00:01 | |* 14 | TABLE ACCESS BY INDEX ROWID | CONNECTOR | 1 | 29 | 2 (0)| 00:00:01 | |* 15 | INDEX UNIQUE SCAN | PK_CONNECTOR | 1 | | 1 (0)| 00:00:01 | ----------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("A1"."RN"=1) 2 - filter(ROW_NUMBER() OVER ( PARTITION BY "A4"."PROD_ID" ORDER BY INTERNAL_FUNCTION("A4"."HIST_TIME") DESC )<=1) 7 - filter("A5"."ITEM_SPEC_ID"=200006) 8 - access("A5"."VALUE"='7') 11 - access("A4"."PROD_ID"=313) 13 - access("A4"."SERV_ID"="A3"."SERV_ID") 14 - filter("A5"."DEVICE_ID"="A2"."DEVICE_ID") 15 - access("A3"."LINE_ID"="A2"."CONNECTOR_ID") Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 2539920 consistent gets 0 physical reads 0 redo size 735 bytes sent via SQL*Net to client 492 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 3 sorts (memory) 0 sorts (disk) 1 rows processed
落落 14:56:39
SELECT COUNT(*)
FROM "RM"."DEVICE_ITEM" "A5"
WHERE "A5"."ITEM_SPEC_ID" = 200006
AND "A5"."VALUE" = '7'
落落 14:56:44
看哈 返回结果
美女QQ 14:58:02
COUNT(*)
----------
68384
落落 15:20:15
select count(*) from H_PROD_2_RF_SERV
where prod_id=313 ;
落落 15:20:18
给出返回结果
美女QQ 15:21:24
正在跑
落落 15:24:03
还没出结果啊。。
美女QQ 15:24:24
select count(*) from rm.H_PROD_2_RF_SERV;
COUNT(*)
----------
17036077
美女QQ 15:24:25
ok
美女QQ 15:24:36
额!错了
美女QQ 15:24:38
等下
美女QQ 15:24:51
select count(*) from rm.H_PROD_2_RF_SERV where prod_id=313 ;
COUNT(*)
----------
6
美女QQ 15:24:56
这个正确
落落 15:33:20
SELECT "A1"."CODE", "A1"."DEVICE_ID", "A1"."SIDEB_PORT_ID", "A1"."VERSION"
FROM (SELECT /*+ use_nl(a4,a3) leading(a4) use_nl(a3,a2) use_hash(a5) */
"A2"."CODE" "CODE",
"A2"."DEVICE_ID" "DEVICE_ID",
"A2"."SIDEB_PORT_ID" "SIDEB_PORT_ID",
"A3"."VERSION" "VERSION",
ROW_NUMBER() OVER(PARTITION BY "A4"."PROD_ID" ORDER BY "A4"."HIST_TIME" DESC) "RN"
FROM "RM"."H_PROD_2_RF_SERV" "A4",
"RM"."H_RSC_FACING_SERV_LINE_ITEM" "A3",
"RM"."CONNECTOR" "A2"
WHERE "A4"."SERV_ID" = "A3"."SERV_ID"
AND "A3"."LINE_ID" = "A2"."CONNECTOR_ID"
AND EXISTS (SELECT 0
FROM "RM"."DEVICE_ITEM" "A5"
WHERE "A5"."DEVICE_ID" = "A2"."DEVICE_ID"
AND "A5"."ITEM_SPEC_ID" = 200006
AND "A5"."VALUE" ='7')
AND "A4"."PROD_ID" = 313) "A1"
WHERE "A1"."RN" = 1
美女QQ 15:33:42
努力成功了!我刚刚在生产库上面测试,0.188秒
下面是优化之后的执行计划
15:50:13 SQL> SELECT "A1"."CODE", "A1"."DEVICE_ID", "A1"."SIDEB_PORT_ID", "A1"."VERSION" 15:50:14 2 FROM (SELECT /*+ use_nl(a4,a3) leading(a4) use_nl(a3,a2) use_hash(a5) */ 15:50:14 3 "A2"."CODE" "CODE", 15:50:14 4 "A2"."DEVICE_ID" "DEVICE_ID", 15:50:14 5 "A2"."SIDEB_PORT_ID" "SIDEB_PORT_ID", 15:50:14 6 "A3"."VERSION" "VERSION", 15:50:14 7 ROW_NUMBER() OVER(PARTITION BY "A4"."PROD_ID" ORDER BY "A4"."HIST_TIME" DESC) "RN" 15:50:14 8 FROM "RM"."H_PROD_2_RF_SERV" "A4", 15:50:14 9 "RM"."H_RSC_FACING_SERV_LINE_ITEM" "A3", 15:50:14 10 "RM"."CONNECTOR" "A2" 15:50:14 11 WHERE "A4"."SERV_ID" = "A3"."SERV_ID" 15:50:14 12 AND "A3"."LINE_ID" = "A2"."CONNECTOR_ID" 15:50:14 13 AND EXISTS (SELECT 0 15:50:14 14 FROM "RM"."DEVICE_ITEM" "A5" 15:50:14 15 WHERE "A5"."DEVICE_ID" = "A2"."DEVICE_ID" 15:50:14 16 AND "A5"."ITEM_SPEC_ID" = 200006 15:50:14 17 AND "A5"."VALUE" ='7') 15:50:14 18 AND "A4"."PROD_ID" = 313) "A1" 15:50:14 19 WHERE "A1"."RN" = 1 15:50:15 20 ; Execution Plan ---------------------------------------------------------- Plan hash value: 3121894527 ---------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 175 | 40 (3)| 00:00:01 | |* 1 | VIEW | | 1 | 175 | 40 (3)| 00:00:01 | |* 2 | WINDOW SORT PUSHED RANK | | 1 | 109 | 40 (3)| 00:00:01 | |* 3 | HASH JOIN SEMI | | 1 | 109 | 39 (0)| 00:00:01 | | 4 | NESTED LOOPS | | 7 | 511 | 33 (0)| 00:00:01 | | 5 | NESTED LOOPS | | 7 | 308 | 19 (0)| 00:00:01 | | 6 | TABLE ACCESS BY INDEX ROWID| H_PROD_2_RF_SERV | 4 | 96 | 7 (0)| 00:00:01 | |* 7 | INDEX RANGE SCAN | IDX_HP2RS_PRODID_SERVID | 4 | | 3 (0)| 00:00:01 | | 8 | TABLE ACCESS BY INDEX ROWID| H_RSC_FACING_SERV_LINE_ITEM | 2 | 40 | 4 (0)| 00:00:01 | |* 9 | INDEX RANGE SCAN | IDX_HRFSLI_SERV | 2 | | 2 (0)| 00:00:01 | | 10 | TABLE ACCESS BY INDEX ROWID | CONNECTOR | 1 | 29 | 2 (0)| 00:00:01 | |* 11 | INDEX UNIQUE SCAN | PK_CONNECTOR | 1 | | 1 (0)| 00:00:01 | |* 12 | TABLE ACCESS BY INDEX ROWID | DEVICE_ITEM | 1 | 36 | 6 (0)| 00:00:01 | |* 13 | INDEX RANGE SCAN | IDX_DEVICE_ITEM_VALE | 9 | | 4 (0)| 00:00:01 | ---------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("A1"."RN"=1) 2 - filter(ROW_NUMBER() OVER ( PARTITION BY "A4"."PROD_ID" ORDER BY INTERNAL_FUNCTION("A4"."HIST_TIME") DESC )<=1) 3 - access("A5"."DEVICE_ID"="A2"."DEVICE_ID") 7 - access("A4"."PROD_ID"=313) 9 - access("A4"."SERV_ID"="A3"."SERV_ID") 11 - access("A3"."LINE_ID"="A2"."CONNECTOR_ID") 12 - filter("A5"."ITEM_SPEC_ID"=200006) 13 - access("A5"."VALUE"='7') Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 14770 consistent gets 0 physical reads 0 redo size 735 bytes sent via SQL*Net to client 492 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 1 rows processed
如果你知道一个SQL应该走什么样的执行计划,那么你就是SQL优化高手了。