最近參加了公司一位DBA關於數據庫性能的分析,覺得講得挺不錯的,因此做下總結,也算是一種積累。
這個博文整體結構分爲三個部分:
第一部分,闡述數據庫的數據存儲結構;
第二部分,SQL性能分析(核心部分);
第三部分,SQL調優實例。
1 數據庫的數據存儲結構
在開始性能優化前,首先需要對優化的對象進行了解,這樣我們才能抓住問題的本質。
頁面(BLOCK)
數據庫中最小的分配,讀取單元,一般來說,設置爲8K大小。
表
數據庫中的表,是由一些列的頁面(block)組成
頁面物理上可以不連續,但是邏輯上是連續的
索引
索引也是由頁面(block)組成
通常採用B+樹的組織形式
2 SQL性能分析(核心部分)
重中之重:一條sql是否ok?如何優化?走索引是否可以提高性能?全在於下面一句話:
此SQL需要訪問多少頁面(BLOCK)!!!
爲什麼是這樣的呢?原因是讀頁面是大量的IO操作,需要在內存中定位,或是外存中定位並加載,開銷很大。而其他的SQL比較操作,>,=,like…,都是CPU計算,相對開銷較小。
下面分別對幾類常見SQL訪問需要讀取的頁面(BLOCK)進行分析:
表全掃描
表中所有的頁面(BLOCK)
索引全掃描
索引中所有的頁面。優勢:索引項相對於表項較小,頁面更少
索引範圍掃描
索引層數+範圍中的BLOCK
索引唯一掃描
索引層數。優勢:最小的頁面訪問量
索引掃描+回表掃描
索引BLOCK+表BLOCK
叢上面的分析可知,索引唯一掃描是最快的,也就是我們平常從某張表中根據唯一的ID查詢一個唯一記錄的SQL;表全掃描是最慢的,也就是需要遍歷表中所有的記錄。
3 SQL調優實例
這裏先說一下,不是每個SQL需要優化的,如果SQL性能滿足需求,是不需要做優化的。
出了性能問題的的SQL:
SELECT *
FROM (select rid
FROM (select r.rid, rownum rnum
FROM (select rowid rid
FROM CREDIT_REMARK t
WHERE t.POSTER_MEMBER_ID = :1 and t.POSTER_ROLE = #memberRole#
ORDER BY t.GMT_REMARK_MODIFIED DESC, t.ID DESC) r
WHERE rownum <= #endRow :INTEGER#)
WHERE rnum > #startRow :INTEGER#) t1,
CREDIT_REMARK t2
WHERE t1.rid = t2.rowid ORDER BY t2.GMT_REMARK_MODIFIED DESC, t2.ID DESC;
解決方案: