NOT IN 一次優化
源語句如下:
select t.id,
t.fundapplyno,
t.applycomcode,
t.transferdate,
t.extaccountno,
t.amount,
t.extaccountname
from ts_transfer t
where t.importtypeid = 3
and t.status in (4, 6)
and t.transferdate > to_date('2012-09-29', 'yyyy-mm-dd')
and t.transferdate < to_date('2012-11-01', 'yyyy-mm-dd')
and t.applycomcode NOT in
(select b.fundapplyno
from gppaymentfund_bz b
where b.amount > 0
and b.fundstatus = 6
and b.fundapplydate > to_date('2012-09-29', 'yyyy-mm-dd')
and b.fundapplydate < to_date('2012-11-01', 'yyyy-mm-dd'))
執行計劃:
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1031211341
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 33064 | 3099K| | 56M
| 1 | SORT ORDER BY | | 33064 | 3099K| 7800K| 56M
|* 2 | FILTER | | | | |
|* 3 | TABLE ACCESS FULL| TS_TRANSFER | 33064 | 3099K| | 5436
|* 4 | TABLE ACCESS FULL| GPPAYMENTFUND_BZ | 1 | 38 | | 1876
--------------------------------------------------------------------------------
這裡雖然有全表掃描但是問題的根源不是全表掃描,也不是在排序。而在於執行計劃選擇了filter,
而filter類似於nestloop的方式進行訪問,效率低下這個語句跑不出結果集或者說要等很久。
通過分析,使用minus來代替了這樣的訪問方式改寫語句如下:
select *
from (select t.id,
t.fundapplyno,
t.applycomcode,
t.transferdate,
t.extaccountno,
t.amount,
t.extaccountname
from ts_transfer t
where t.importtypeid = 3
and t.status in (4, 6)
and t.transferdate > to_date('2012-3-31', 'yyyy-mm-dd')
and t.transferdate < to_date('2012-11-01', 'yyyy-mm-dd')
minus
select t.id,
t.fundapplyno,
t.applycomcode,
t.transferdate,
t.extaccountno,
t.amount,
t.extaccountname
from ts_transfer t
where t.importtypeid = 3
and t.status in (4, 6)
and t.transferdate > to_date('2012-3-31', 'yyyy-mm-dd')
and t.transferdate < to_date('2012-11-01', 'yyyy-mm-dd')
and t.applycomcode in
(select b.fundapplyno
from gppaymentfund_bz b
where b.amount > 0
and b.fundstatus = 6
and b.fundapplydate > to_date('2012-2-29', 'yyyy-mm-dd')
and b.fundapplydate < to_date('2012-11-01', 'yyyy-mm-dd')))
order by transferdate desc;
同時建立了索引
SQL> create index gaopengtest2 on gppaymentfund_bz(fundapplydate,fundstatus,amount,fundapplyno);
Index created
SQL> create index gaopengtest1 on ts_transfer(transferdate,IMPORTTYPEID);
Index created
所以test2的意思在於讓訪問走INDEX FAST FULL SCAN,而索引TEST1的意思在於當日期取值範圍較小時可以走索引範圍掃描。但是這裡是用不到的。
而filter類似於nestloop的方式進行訪問,效率低下這個語句跑不出結果集或者說要等很久。
通過分析,使用minus來代替了這樣的訪問方式改寫語句如下:
select *
from (select t.id,
t.fundapplyno,
t.applycomcode,
t.transferdate,
t.extaccountno,
t.amount,
t.extaccountname
from ts_transfer t
where t.importtypeid = 3
and t.status in (4, 6)
and t.transferdate > to_date('2012-3-31', 'yyyy-mm-dd')
and t.transferdate < to_date('2012-11-01', 'yyyy-mm-dd')
minus
select t.id,
t.fundapplyno,
t.applycomcode,
t.transferdate,
t.extaccountno,
t.amount,
t.extaccountname
from ts_transfer t
where t.importtypeid = 3
and t.status in (4, 6)
and t.transferdate > to_date('2012-3-31', 'yyyy-mm-dd')
and t.transferdate < to_date('2012-11-01', 'yyyy-mm-dd')
and t.applycomcode in
(select b.fundapplyno
from gppaymentfund_bz b
where b.amount > 0
and b.fundstatus = 6
and b.fundapplydate > to_date('2012-2-29', 'yyyy-mm-dd')
and b.fundapplydate < to_date('2012-11-01', 'yyyy-mm-dd')))
order by transferdate desc;
同時建立了索引
SQL> create index gaopengtest2 on gppaymentfund_bz(fundapplydate,fundstatus,amount,fundapplyno);
Index created
SQL> create index gaopengtest1 on ts_transfer(transferdate,IMPORTTYPEID);
Index created
所以test2的意思在於讓訪問走INDEX FAST FULL SCAN,而索引TEST1的意思在於當日期取值範圍較小時可以走索引範圍掃描。但是這裡是用不到的。
改寫後執行計劃如下:
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 480831536
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 33064 | 10M| | 14513
| 1 | SORT ORDER BY | | 33064 | 10M| 21M| 14513
| 2 | VIEW | | 33064 | 10M| | 12258
| 3 | MINUS | | | | |
| 4 | SORT UNIQUE | | 33064 | 3099K| 7800K| 6154
|* 5 | TABLE ACCESS FULL | TS_TRANSFER | 33064 | 3099K| | 5424
| 6 | SORT UNIQUE | | 2922 | 382K| 872K| 6104
|* 7 | HASH JOIN | | 2922 | 382K| 2856K| 6014
|* 8 | INDEX FAST FULL SCAN| GAOPENGTEST2 | 58355 | 2165K| | 284
|* 9 | TABLE ACCESS FULL | TS_TRANSFER | 30125 | 2824K| | 5436
--------------------------------------------------------------------------------
最後ORACLE使用HASHjion 代替了IN ,語句的執行時間也優化到9秒。
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 480831536
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 33064 | 10M| | 14513
| 1 | SORT ORDER BY | | 33064 | 10M| 21M| 14513
| 2 | VIEW | | 33064 | 10M| | 12258
| 3 | MINUS | | | | |
| 4 | SORT UNIQUE | | 33064 | 3099K| 7800K| 6154
|* 5 | TABLE ACCESS FULL | TS_TRANSFER | 33064 | 3099K| | 5424
| 6 | SORT UNIQUE | | 2922 | 382K| 872K| 6104
|* 7 | HASH JOIN | | 2922 | 382K| 2856K| 6014
|* 8 | INDEX FAST FULL SCAN| GAOPENGTEST2 | 58355 | 2165K| | 284
|* 9 | TABLE ACCESS FULL | TS_TRANSFER | 30125 | 2824K| | 5436
--------------------------------------------------------------------------------
最後ORACLE使用HASHjion 代替了IN ,語句的執行時間也優化到9秒。
一句話優化SQL必須找到問題的根源,並不是平空猜測的。如果憑空猜測也許很多人要把這裡的NOT IN 改為NOT EXISTS 實際上ORACLE 10G 後這樣的代替沒有什麼意義。NOT IN和NOT EXISTS 是等價的。(不知道9I怎麼樣)
當然這裡的代替只適合結果集1中沒有重複的記錄。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-750120/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 一次優化優化
- EntityFramework優化:第一次啟動優化Framework優化
- 記一次UITableView優化UIView優化
- 記一次sql優化SQL優化
- 一次 Flutter WebView 效能優化FlutterWebView優化
- ? 記一次前端效能優化前端優化
- 記一次分頁優化優化
- 記錄一次打包優化優化
- 一次成功的優化案例優化
- 一次sql優化小記SQL優化
- 記一次 Webpack 專案優化Web優化
- 一次Oracle優化所想到的Oracle優化
- 記一次Elasticsearch優化總結Elasticsearch優化
- 記一次golang的gzip優化Golang優化
- 一次UnionAll的合併優化優化
- 記一次效能優化經歷優化
- 對Hash Join的一次優化優化
- 一次移動優化之旅(二)優化
- 漫漫優化路,總會錯幾步(記一次介面優化)優化
- 記一次 spinor flash 讀速度優化優化
- 記一次公司產品「負」優化優化
- 一次簡單的分頁優化優化
- 記一次Node專案的優化優化
- 記MySQL一次關於In的優化MySql優化
- 記一次前端效能優化的案例前端優化
- 一次簡單的程式碼優化優化
- 一次HASH JION過慢優化(2)優化
- 一次HASH JION過慢優化(1)優化
- 一次效能優化調整過程.優化
- 一次sql語句優化的反思SQL優化
- 一次分頁查詢的優化優化
- Go藉助PProf的一次效能優化Go優化
- 一次生產的 JVM 優化案例JVM優化
- 記一次 VUE 專案優化實踐Vue優化
- 一次資料庫的優化經歷資料庫優化
- 記一次Prometheus代理效能優化問題Prometheus優化
- 記一次提升18倍的效能優化優化
- 涉及子查詢sql的一次優化SQL優化