未考虑将需求最小化
需求最小化
這個SQL語句其實是為了實現行列轉換,但是效率非常低,掃描表多次,而且最終結果也不正確。如何進行分析呢: 1.首先了解該語句的需求是什么,經了解,需求如下: DROP TABLE TEST; CREATE TABLE TEST ( ID1 NUMBER,ID2 NUMBER,VALUE1 VARCHAR2(20),VALUE2 VARCHAR2(20)); INSERT INTO TEST VALUES (1,2,'A','B'); INSERT INTO TEST VALUES (1,2,'C','D'); INSERT INTO TEST VALUES (1,2,'E','F'); INSERT INTO TEST VALUES (1,2,'G','H'); INSERT INTO TEST VALUES (3,8,'I','J'); INSERT INTO TEST VALUES (3,8,'K','L'); INSERT INTO TEST VALUES (3,8,'M','N'); INSERT INTO TEST VALUES (8,9,'O','P'); INSERT INTO TEST VALUES (8,9,'Q','R'); INSERT INTO TEST VALUES (11,12,'S','T'); COMMIT; SQL> SELECT * FROM TEST; ID1 ID2 VALUE1 VALUE2 ---------- ---------- -------------------- --------------------1 2 A B1 2 C D1 2 E F1 2 G H3 8 I J3 8 K L3 8 M N8 9 O P8 9 Q R11 12 S T 10 rows selected 要求為(行列轉換,超過3個的只取三個,不足3個的用空格來補列) ID1 ID2 VALUE1 VALUE2 VALUE3 VALUE4 VALUE5 VALUE6 ---------- ---------- -------------------- ------------------------------------------------------------- 1 2 A B C D E F 3 8 I J K L M N 8 9 O P Q R NULL NULL 11 12 S T NULL NULL NULL NULL我們可以通過MAX+分析函數實現如下: SELECT ID1,ID2,MAX(DECODE(RN,1,VALUE1)),MAX(DECODE(RN,1,VALUE2)),MAX(DECODE(RN,2,VALUE1)),MAX(DECODE(RN,2,VALUE2)),MAX(DECODE(RN,3,VALUE1)),MAX(DECODE(RN,3,VALUE2))FROM (SELECT TEST.*, ROW_NUMBER() OVER(PARTITION BY ID1,ID2 ORDER BY VALUE1,VALUE2) RN FROM TEST) T WHERE RN<=3 GROUP BY ID1,ID2;于是可以將SQL改造為如下(這樣的語句將表掃描由原來的3次降低為1次,大大提升了性能,而且原先的語句還存在邏輯上的錯誤) WITH T AS (select hopbyhop,svcctx_id,substr(cause,instr(cause, 'Host = ') + 7,instr(cause, 'Priority = ') - instr(cause, 'Host = ') - 11) peer,substr(cause,instr(cause, 'Priority = ') + 11,instr(cause, 'reachable = ') -instr(cause, 'Priority = ') - 13) priorityfrom dcc_sys_logwhere cause like '%SC路由應答%'and hopbyhop in (select distinct hopbyhop from dcc_sys_log))---此處多余! SELECT hopbyhop,svcctx_id,MAX(DECODE(RN,1,PEER)) PEER1,MAX(DECODE(RN,1,PRIORITY)) PRIORITY1,MAX(DECODE(RN,2,PEER)) PEER2,MAX(DECODE(RN,2,PRIORITY)) PRIORITY2,MAX(DECODE(RN,3,PEER)) PEER3,MAX(DECODE(RN,3,PRIORITY)) PRIORITY3FROM (SELECT T.*, ROW_NUMBER() OVER(PARTITION BY hopbyhop,svcctx_id ORDER BY PEER,PRIORITY) RN FROM T) WHERE RN<=3 GROUP BY hopbyhop,svcctx_id;注:涉及到結果集多次使用的時候,盡量用WITH子句,來減少代碼,并且易于維護,這個WITH子句處的處理邏輯如下, 只是為了取出Host = 的值和Priority = 的值SQL> SELECT substr('SC路由應答:Host = SR2@001.ChinaTelecom.com, Priority = 1, reachable = true',2 instr('SC路由應答:Host = SR2@001.ChinaTelecom.com, Priority = 1, reachable = true', 'Host = ') + 7,3 instr('SC路由應答:Host = SR2@001.ChinaTelecom.com, Priority = 1, reachable = true', 'Priority = ') - instr('SC路由應答:Host = SR2@001.ChinaTelecom.com, Priority = 1, reachable = true', 'Host = ') - 11) peer,4 substr('SC路由應答:Host = SR2@001.ChinaTelecom.com, Priority = 1, reachable = true',5 instr('SC路由應答:Host = SR2@001.ChinaTelecom.com, Priority = 1, reachable = true', 'Priority = ') + 11,6 instr('SC路由應答:Host = SR2@001.ChinaTelecom.com, Priority = 1, reachable = true', 'reachable = ') -7 instr('SC路由應答:Host = SR2@001.ChinaTelecom.com, Priority = 1, reachable = true', 'Priority = ') - 13) priority8 from dual;PEER PRIORITY ---------------------- -------- SR2@001.ChinaTelecom.c 1寫死長度比較不科學,萬一數據變化了,值就錯誤了,寫相對位置也比較簡單,只要能將層次分清楚即顯的簡單: with data as (SELECT 'SC路由應答:Host = SR2@001.ChinaTelecom.com, Priority = 1, reachable = true' as str ,'Host = ' k1,'Priority = ' k2FROM DUAL) ,data2 AS (SELECT data.*,INSTR(str,k1) p1,INSTR(str,k2) p2 FROM data) select SUBSTR(str,p1+LENGTH(k1),INSTR(str,',',p1+1)-p1-LENGTH(k1)),SUBSTR(str,p2+LENGTH(k2),INSTR(str,',',p2+1)-p2-LENGTH(k2))from data2;因此本案例的代碼應該為如下:with data as (select hopbyhop,svcctx_id,cause as str,'Host = ' k1,'Priority = ' k2 from dcc_sys_log where cause like '%SC路由應答%') ,data2 as (select data.*,instr(str,k1) p1, instr(str,k2) p2 from data) ,data3 as (select hopbyhop,svcctx_id,SUBSTR(str,p1+LENGTH(k1),INSTR(str,',',p1+1)-p1-LENGTH(k1)) peer,SUBSTR(str,p2+LENGTH(k2),INSTR(str,',',p2+1)-p2-LENGTH(k2)) PRIORITYfrom data2) SELECT hopbyhop,svcctx_id,MAX(DECODE(RN,1,PEER)) PEER1,MAX(DECODE(RN,1,PRIORITY)) PRIORITY1,MAX(DECODE(RN,2,PEER)) PEER2,MAX(DECODE(RN,2,PRIORITY)) PRIORITY2,MAX(DECODE(RN,3,PEER)) PEER3,MAX(DECODE(RN,3,PRIORITY)) PRIORITY3FROM (SELECT data3.*, ROW_NUMBER() OVER(PARTITION BY hopbyhop,svcctx_id ORDER BY PEER,PRIORITY) RN FROM data3) WHERE RN<=3 GROUP BY hopbyhop,svcctx_id;執行計劃: Execution Plan ---------------------------------------------------------- Plan hash value: 3725476352------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | ------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 13 | 6838 | | 16295 (1)| 00:03:16 | | 1 | SORT GROUP BY NOSORT | | 13 | 6838 | | 16295 (1)| 00:03:16 | |* 2 | VIEW | | 246K| 123M| | 16295 (1)| 00:03:16 | |* 3 | WINDOW SORT PUSHED RANK| | 246K| 6994K| 18M| 16295 (1)| 00:03:16 | |* 4 | TABLE ACCESS FULL | DCC_SYS_LOG | 246K| 6994K| | 14321 (1)| 00:02:52 | -------------------------------------------------------------------------------------------------Predicate Information (identified by operation id): ---------------------------------------------------2 - filter("RN"<=3)3 - filter(ROW_NUMBER() OVER ( PARTITION BY "HOPBYHOP","SVCCTX_ID" ORDER BYSUBSTR("CAUSE",INSTR("CAUSE",'Host = ')+7,INSTR("CAUSE",',',INSTR("CAUSE",'Host =')+1)-INSTR("CAUSE",'Host = ')-7),SUBSTR("CAUSE",INSTR("CAUSE",'Priority =')+11,INSTR("CAUSE",',',INSTR("CAUSE",'Priority = ')+1)-INSTR("CAUSE",'Priority =')-11))<=3)4 - filter("CAUSE" LIKE '%SC路由應答%')Statistics ----------------------------------------------------------1 recursive calls0 db block gets64452 consistent gets0 physical reads0 redo size782 bytes sent via SQL*Net to client481 bytes received via SQL*Net from client1 SQL*Net roundtrips to/from client1 sorts (memory)0 sorts (disk)0 rows processedSQL> 最終代碼為select distinct to_char(svcctx_id),to_char(0),to_char(nvl((select peer_idfrom dcc_ne_configwhere peer_name = PEER1),0)),to_char(priority1),to_char(nvl((select peer_idfrom dcc_ne_configwhere peer_name =PEER2),0)),to_char(priority2),to_char(nvl((select peer_idfrom dcc_ne_configwhere peer_name = PEER3),0)),to_char(priority3)from (with data as (select hopbyhop,svcctx_id,cause as str,'Host = ' k1,'Priority = ' k2 from dcc_sys_log where cause like '%SC路由應答%') ,data2 as (select data.*,instr(str,k1) p1, instr(str,k2) p2 from data) ,data3 as (select hopbyhop,svcctx_id,SUBSTR(str,p1+LENGTH(k1),INSTR(str,',',p1+1)-p1-LENGTH(k1)) peer,SUBSTR(str,p2+LENGTH(k2),INSTR(str,',',p2+1)-p2-LENGTH(k2)) PRIORITYfrom data2) SELECT hopbyhop,svcctx_id,MAX(DECODE(RN,1,PEER)) PEER1,MAX(DECODE(RN,1,PRIORITY)) PRIORITY1,MAX(DECODE(RN,2,PEER)) PEER2,MAX(DECODE(RN,2,PRIORITY)) PRIORITY2,MAX(DECODE(RN,3,PEER)) PEER3,MAX(DECODE(RN,3,PRIORITY)) PRIORITY3FROM (SELECT data3.*, ROW_NUMBER() OVER(PARTITION BY hopbyhop,svcctx_id ORDER BY PEER,PRIORITY) RN FROM data3) WHERE RN<=3 GROUP BY hopbyhop,svcctx_id) t2未考慮將需求最小化(催人淚下的SQL續集)
?
?
?
總結