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 結論
得出原因:索引有一個單獨的塊存儲,根據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);