oracle開發系列(三)TABLE ACCESS BY INDEX ROWID 你不知道的索引回表,rowid回表
1 引言
最近系統經常提示一個sql查詢時間過長的問題,看了一下就是一個每天按照時間戳記統計前一天量的sql。
表總的資料量為53483065。
語句如下:
select count(x.serial_id) as countnum from iodso.qos_cnst_busilog_td x where x.oper_time between trunc(sysdate- 1) and trunc(sysdate);
執行時間情況如下:(執行要49s)
看了下執行計畫 是這樣的:
從上面的執行計畫來看 也是走了索引的 是索引範圍掃描。
2 解決
搞不明白 ,決定用count(*) 試試。
執行時間情況如下:
時間很快,1s不到。差別很大,感覺很奇怪 就比較了一下 兩者的執行計畫,下面是count(*)的執行計畫
對比了下 發現 慢的那個 多了個 TABLE ACCESS BY INDEX ROWID。
3 結論
得出原因:索引有一個單獨的Block Storage,根據oper_time 統計表的資料量時 只需要在索引的塊裡面統計資料量就可以了,所以比較快。
那個count(serialid) :
Oracle 索引中儲存的是我們欄位的值和該值對應的rowid,我們根據索引進行尋找,索引範圍掃描後,就會返回該block的rowid,然後根據rowid直接去block上去我們需要的資料,因此就出現了:TABLE ACCESS BY INDEX ROWID
因為還要根據rowid回表的資料區塊上查詢資料,所以速度慢了很多。
4 備忘:
下面兩個查詢的執行時間也很快,因為執行計畫與count(*)都是一樣的。
select COUNT(x.oper_time) AS countnum
fromiodso.qos_cnst_busilog_td x
where x.oper_timebetween trunc(sysdate - 1) and trunc(sysdate);
select COUNT(1) AS countnum
fromiodso.qos_cnst_busilog_td x
where x.oper_timebetween trunc(sysdate - 1) and trunc(sysdate);