要寫出高效的SQL,那麼必須必須得清楚SQL執行路徑,介紹如何提升SQL性能的文章不少,這裏再也不贅述,本人來談談如何從 減小SQL回表次數 來提升查詢性能,由於回表將致使掃描更多的數據塊。sql
咱們你們都知道,數據庫表中數據存儲都是以塊爲單位,稱爲數據塊;表中每行數據都有惟一的地址標誌ROWID。數據庫
舉個例子:性能
select a from test_db where b=5spa
A、假設b上沒有索引orm
一、那麼該條SQL將進行表掃描,掃描全部該表的數據塊索引
二、從數據塊中找到記錄,而且進行過濾it
可想而知,沒有索引將會致使掃描該表全部數據塊,性能低下table
B、 假設b上有索引test
一、那麼該條SQL將進行索引掃描,在索引中找到b=5的位置,通常只須要掃描3個塊左右就找到了select
二、得到全部b=5的行的rowid
三、根據rowid再查詢數據(這就是回表),若是數據量少,那麼回表次數就少,若是須要的數據所有在索引中,那麼就不會再回表了,例如a也在索引中,若是a不在索引中,那麼仍然要回表一次查出a。
經驗:若是有可能的話,儘可能只在索引上查詢,不用回表或者只少許回表。
例如分頁須要回表,通常儘可能在索引上分頁,而後返回rowid,再經過rowid進行回表查詢。
下面是一個經常使用的分頁語句:
Select * from (select row_number over(order by a) rn,t.* from table t where b=? And c=?) where rn>=1 and rn <=20
Select * from (select row_number over(order by a) rn,t.* from table t where b=? And c=?) where rn>=1 and rn <=20
咱們分析一下(假設索引是b,c,a):
一、先查詢內層語句 select * from table t where b=? and c=?,假設返回1000行數據
二、經過索引找到這1000行數據的rowid,由於索引是連續的,假設這1000行數據的索引分佈在5個塊中,則差很少爲8塊讀
三、再根據rowid取回表查詢數據,最壞的狀況是這1000行數據分佈在1000個塊中,則須要讀取1000塊。那麼算上上面的8塊總共堯都區1000+8=1008塊
咱們換一種寫法:
Select * from table t,
(select rid from (select rowid rid,row_number over(order by a) rn from table where b=? And c=?)
where rn>=1 and rn<=20) tmp
Where tmp.rid=t.rowid
Select * from table t,
(select rid from (select rowid rid,row_number over(order by a) rn from table where b=? And c=?)
where rn>=1 and rn<=20) tmp
Where tmp.rid=t.rowid
再來分析一下:
一、最裏層的sql select rid from (select rowid rid,row_number over(order by a) rn from table where b=? And c=?) where rn>=1 and rn<=20 能夠所有從索引中得到數據,因爲索引有序,差很少也是8塊讀
二、分頁以後,只有20行數據,再根據這20行的rowid回表查詢數據,最壞狀況是20行都在20個不一樣塊中,那麼總共20+8=28
從以上分析能夠看出,有效的利用索引,減小回表次數,能夠大大提升SQL性能,值得你們去花功夫瞭解一下。