1. 程式人生 > >高階資料庫十五:查詢優化器(一)

高階資料庫十五:查詢優化器(一)

Optimizer Implementation(Part I)

背景

在講述這個優化器的時候,就必須先了解查詢過程。在本系列的資料庫四:淺談資料庫查詢過程(Query Processing)中大致地說明了一下資料庫的查詢過程,但是沒提到查詢優化器的具體策略與實現。

對於查詢而言,我們期望優化器的作用是找到最小代價的正確執行方案。但是這是一個NP完全問題,所以沒有一個優化器能夠真正地找到真正的最佳方案。

關於OLTP的查詢優化會更加簡單,一般來說選取最好的索引,JOIN操作也大多使用外來鍵,用一些簡單的策略就行。

比如,大家可以畫一棵關係代數查詢樹,如果我們將選擇操作儘可能下放到深處,則在進行笛卡爾乘或者JOIN的時候,參與運算的資料就少了。這就是heuristic optimazation。

所以在這兒我們將說明OLAP查詢的優化策略。

優化器基礎

優化器粒度

單查詢

  • 更小的搜尋空間。
  • DBMS不能在查詢中重複使用結果。
  • 為了解決資源爭奪問題,成本模型必須考慮當前正在執行的內容。

多查詢

  • 如果有很多類似的查詢,效率會更高。
  • 搜尋空間要大得多。
  • 用於掃描共享(之後的文章會提到,大致就是多個查詢共用一個掃描表的結果,而不是各自掃描一次)

優化時間

靜態優化

  • 在執行之前選擇最佳計劃。
  • 計劃質量取決於成本模型的準確性。
  • 可以使用準備好的支票分攤執行。

動態優化

  • 主要在流式資料的時候使用
  • 查詢執行時,即時選擇運營商計劃。
  • 將重新優化多次執行。
  • 難以實現/除錯(非確定性)

混合優化

  • 使用靜態演算法編譯。
  • 如果估計>閾值的誤差,則重新優化。

計劃穩定

提示

  • 執行資料庫系統管理員幫助優化器進行決策,比如,我希望用hash表進行JOIN等
  • mysql、sqlserver似乎都支援這種方法

固定優化器版本

  • 設定優化器版本號並將查詢逐個遷移到新優化器。比如,雖然用了新版本的資料庫,但是對於某種特定的查詢,我們發現了舊版本的優化器似乎更快,則可以將版本調回去。

向後相容的計劃

  • 從舊版本儲存備份查詢計劃,並將其提供給新的DBMS。

優化器搜尋策略

Heuristics

之前舉了一個關係代數查詢樹的例子,說的就是Heuristics優化方法。它定義了一些規則,通過靜態的方式來進行優化:

  • 儘早進行選擇,越嚴格的限制應該越早進行
  • 在連線之前執行所有選擇
  • 謂詞/限制/投影下推
  • 基於基數加入排序

Oracle在早起非常受歡迎的原因就是因為它使用了這種方法。

優點:

  • 易於實施和除錯。
  • 效果相當好,對於簡單的查詢很快。

缺點:

  • 依靠玄學常數來預測計劃決策的有效性。
  • 當操作之間存在複雜的相互依賴關係時,幾乎不可能產生好的查詢計劃。

使用靜態規則執行初始優化,然後使用動態規劃來確定表格的最佳連線順序。

  • 第一個基於成本的查詢優化器
  • 使用分而治之搜尋方法進行自底向上(向前連結)

現在也非常常用的技術,MySQL、SQLite都用這個。

SYSTEM R OPTIMIZER

假設都沒有索引,則得到資料的方式就是線性掃描。

然後將所有的JOIN操作的可能性都列出來,並找出最少代價的JOIN策略。其中也包括每個具體的JOI操作的演算法。

因為有ORDER BY,所以要進行排序

優點:

  • 通常找到一個合理的計劃,而不必執行詳盡的搜尋。

缺點:

  • 所有與啟發式方法相同的問題。
  • 左深連線樹並不總是最佳的。
  • 必須考慮成本模型中資料的物理屬性(例如排序順序)。

Randomized Algorithms

執行隨機遍歷查詢的所有可能(有效)計劃的解決方案空間。
繼續搜尋,直到達到代價閾值或優化器執行一段特定的時間。

例如:Postgres的遺傳演算法。

優點:

  • 隨機跳轉搜尋空間允許優化器跳出區域性最小值(這個地方可以去看看遺傳演算法的文章來理解原理)。
  • 低記憶體開銷(如果沒有歷史儲存)。

缺點:

  • 很難確定為什麼DBMS可能選擇了一個特定的計劃。
  • 必須做額外的工作來確保查詢計劃是確定性的。
  • 仍然必須執行正確性規則。

SIMULATED ANNEALING

用Heuristics方發生成的最初的查詢計劃,然後通過SQL運算子的隨機排列(例如,交換兩個表的連線順序)來產生新的解。

  • 始終接受降低成本的更改
  • 只接受一個可能會增加成本的變化。
  • 拒絕違反正確性的任何更改(例如,排序順序)

POSTGRES OPTIMIZER

更復雜的查詢使用遺傳演算法來選擇連線順序的。

在每一輪開始時,生成查詢計劃的不同版本,選擇成本最低的計劃,並用其他計劃進行排列。重複該操作。

  • 變異函式只產生有效的計劃。

首先使用轉換規則重寫邏輯查詢計劃。

  • 引擎檢查是否允許轉換,然後才能應用。
  • 這一步從來不考慮成本。

然後執行基於成本的搜尋,從而將邏輯查詢計劃對映到物理查詢計劃。

優點:

  • 在快速表現的實踐中運作良好。

缺點:

  • 難以為轉換指定優先順序
  • 如果不計算多重成本估算,一些轉換難以評估。
  • 規則維護是一個巨大的痛苦。

STARBURST OPTIMIZER

用此方法實現更好地System R optimizer。

階段1:查詢重寫

  • 計算查詢的SQL塊級關係微積分表示。

階段2:計劃優化

  • 一旦查詢重寫完成,執行System RR風格的動態規劃階段。

使用唯一的一個搜尋空間,統一邏輯- 邏輯和邏輯- 物理轉換的概念。 不需要單獨的階段,因為一切都是轉換。

這種方法產生了更多的轉換,因此大量使用memoization來減少冗餘工作。

VOLCANO OPTIMIZER

通用基於成本的查詢優化器,基於關係代數上的等價規則。

  • 輕鬆新增新的操作和等價規則。
  • 計劃過程中將資料的物理屬性視為一流的實體。
  • 使用分枝定界搜尋的自頂向下方法(反向連結)。

不過這種方法似乎只在實驗室或者學校中才有用到,工業界似乎沒有用過這種方式。

優點

  • 使用宣告性規則來生成轉換。
  • 通過高效的搜尋引擎實現更好的可擴充套件性。 減少使用記憶的冗餘估計。

缺點:

  • 在優化搜尋之前,所有等價類都完全展開以生成所有可能的邏輯運算子。
  • 不容易修改謂詞。

TOP-DOWN VS. BOTTOM-UP

自上而下的優化:從你想要的最終結果開始,然後在樹上尋找最適合你的目標。

自下而上的優化:從一無所有開始,然後制定計劃以達到您想要的最終結果。