干貨|Oracle復雜視圖優化案例分析
在使用Oracle數據庫過程中,視圖是作為數據庫對象存在的,因而,在創建了這樣的視圖后,就可以通過工具或者數據字典來查看視圖的相關信息。視圖來源于表,所有對視圖數據的修改最終都會被反映到視圖的基表中,這些修改必須服從基表的完整性約束,并同樣會觸發定義在基表上的觸發器。
Oracle的視圖分為簡單視圖和復雜視圖兩種,簡單視圖就是從單一的表中獲取數據,其中不包含函數和數據組等,復雜視圖是指在視圖定義中包括了聚合函數、分析函數、用戶自定義函數、多表關聯、子查詢等。此類視圖在某些特定條件下,優化器無法將視圖外的謂詞條件推送至視圖內的基表上,即使在基表的列上創建索引也無法使用索引。本文將對該類視圖提出一種優化方案,可以顯著提高該類視圖的性能,而且表的數據量越大,查詢數據越少,性能提高越明顯。下面,本文在實操基礎上,對影響謂詞推入因素及如何優化進行簡要闡釋。
影響謂詞推入因素
本文的實驗環境是Oracle 11.2.0.4版本的數據庫,筆者通過反復測試發現,若查詢語句中存在以下兩種情況,則優化器會阻止視圖謂詞條件推入至基表上:一是視圖中的查詢中包括了ROWNUM偽列;二是視圖中含有分析函數(如ROW_NUMBER() OVER(…))。若遇其它影響謂詞推入的情況優化方法與此方法類似。另外,Oracle 11.2.0.4之前的版本可能存在其它影響謂詞推入的情況。
優化方法
如果可以將這類視圖中常用的謂詞條件直接寫入視圖內,且寫成動態的,同時將常用查詢列按選擇性由大至小創建組合索引,則優化器可以盡可能地使用索引直接獲取數據,再進行過濾計算等操作,以此達到優化目的。具體操作步驟如下:
(1)創建一個輔助包,并創建兩個函數,實際情況中若同時傳入多個條件可自行擴充包中方法,每一個條件需要增加兩個方法。
(2)修改視圖定義,將謂詞條件寫入至基表條件中,并重新編譯視圖。
性能對比
下面通過具體的例子來說明如何對復雜視圖進行優化。
通過將原視圖和優化后視圖進行對比,看出優化后視圖的執行計劃成本由349降到86,優化效果非常明顯。表中紅框部分內容需特別引起注意。
優化前視圖查詢的執行計劃是全表掃描,執行效率低下。優化后視圖查詢的執行計劃是索引范圍掃描。通過索引直接取出需要訪問的數據,再進行后續處理,性能較優化前有大幅提升。
需要指出的是,該方法只在訪問視圖中少量數據時效果明顯,如果訪問數據量大,該方法不適用。
表4.1 優化前視圖定義、查詢語句及執行計劃
表4.2 優化后視圖定義、查詢語句及執行計劃
通過以上分析對比可以清晰地看出,優化后的視圖可以使用索引且性能有了顯著提高。總結起來,對于復雜查詢優化思路應該是:如果視圖中訪問的是少量數據,則盡可能通過索引先取出需要處理的數據,然后再進行后續處理。此方法適用的前提是,復雜視圖使用各種常規優化方法(如增加索引,添加提示符等)都無效時。
但是,這一方法也有一定弊端,那就是與其它優化方法相比,此法需要做的前期工作較多,如建立輔助包,對原視圖進行修改和重新編譯。另外還需測試優化前后查詢結果是否一致,查詢前需調用輔助包,將查詢條件傳入視圖中,不過優化后的視圖是不需要加查詢條件的。