數據庫等值查詢與統計信息

簡介: 統計信息是爲優化器的 cost 估算提供數據支撐,其中很重要的一點需求便是等值查詢(EQUALS, IN 等) 場景下的基數估算。

概念

統計信息是爲優化器的 cost 估算提供數據支撐,其中很重要的一點需求便是等值查詢(EQUALS, IN 等) 場景下的基數估算。考慮以下 Case

CREATE TABLE `mc_tac_template` (
  `ID` BIGINT ,
  `NAME` varchar(50) NOT NULL,
  `GENDER` varchar(10) NOT NULL,
  PRIMARY KEY (`ID`),
  KEY `KEY_NAME` USING BTREE (`NAME`),
  KEY `KEY_GENDER` USING BTREE (`GENDER`)
) 

SELECT * FROM User WHERE Name='wy' AND Gender='female'

我們的客戶同時爲性別和姓名設置了索引,這時優化器就要基於各個條件過濾行數多寡來估算選擇不同索引的代價開銷。就這個 case 而言,如果選到了 gender 的索引,查詢過程很可能就不太妙了。

如果統計信息可以提供精確基數,例如 Name='wy' 可以過濾出5行, Gender='female' 只能過濾出一半的數據, 優化器就會知道,此時選擇 KEY_NAME 是代價更小的選擇。

爲了支撐這裏的估算過程,統計信息需要決定使用什麼樣的算法,這也決定了如何收集,如何估算。

算法

數據庫中的基數估算類似於 Data Sketching,等值場景下的基數估算一般有兩種選擇,基於 sample 或基於全量數據。

SAMPLE

當數據量增長時, sample 是一種非常有效提升估算效率的手段。但 sample 必須至少面對以下問題
● 採樣的隨機化
● 採樣數據與整體數據間的差異估算
○ 多少 sample 量才能確保誤差率
● 當新數據出現時,如何採樣

採樣隨機化是個很現實的問題,例如存儲中的採樣有兩種做法, 一種按頁採樣,一種是每頁都採一部分數據。第一種方案雖然非常高效,但隨機性太差很容易導致估算的效果非常差,第二種方案雖然估算效果高一些,但在 IO 上相當於全量掃描了一遍。

3.png

在 Every Row Counts: Combining Sketches and Sampling for Accurate Group-By Result Estimates 這篇論文中,作者比較了基於 Sample 的 GEE/AE 與面向全量數據的 HyperLogLog sketch 算法,HyperLogLog 的精確度完勝。當然這僅僅是在計算 NDV 的場景。

當我們需要某個單一確定數據在集羣中的特徵時, sample 都很難回答該類問題。舉個例子,數據的存在問題,即某數據是否在集羣中存在,如果該數據不在 sample 集中存在,那既有可能整體中也不存在,也有可能只是沒有被 sample 到。

再例如通過採樣估算 ndv 時,如果採樣數據(假設 100000 行) 中 ndv 接近 100000,那麼整體數據(假設 10000000行)的 ndv 有可能是 100000,或者也有可能是 10000000。

NDV: number of the different value

Sample 的數據集更適合用於解答範圍條件下數據的特徵問題。例如通過 sample 的數據來構建直方圖,用於處理範圍條件的查詢問題,或者通過 sample 集估算多表等值 Join 的基數問題等。這些問題不在本文的討論範圍內,暫不展開。

非 Sample

● frequency:等值場景的基數估算就是獲取某值在集合中的數量,也就是一個獲取 frequency 的問題

CountMin Sketch

CountMin Sketch 通常用於解決 frequency 問題。它有點像 Bloom filter,同樣需要一個數組以及一個 Hash 函數的集合,當遍歷數據時,每個數據會被各個 Hash 函數 Map 到數組中的某個位置,並使該位置的計數器加1。在估算環節,取該數據對應所有計數器所得的最小值。可以預見它一定會確保估算值大於等於真實值,然後再通過一些手段確保誤差率。具體的原理這裏不再贅述。

CountMin Sketch 具體原理見 An Improved Data Stream Summary:The Count-Min Sketch and its Applications

4.png

CountMin Sketch 最大的問題是當 Sketch 大小不合適時,很容易因 Hash collision 出現過度膨脹的估算。不管是增大 rows (即 Hash 函數)數量或 columns (即 Counter)的數量,都可以減少錯誤率。CountMin Sketch 在處理大量重複數據時很有優勢,但在處理非傾斜數據時,很容易產生過於膨脹的結果。

當然,最開始 CountMin 也是用於處理熱點數據獲取這種場景。但在數據分佈比較均勻的場景並不十分友好。

HyperLogLog+TopN

在 PolarDB-X 中,我們權衡之後使用 HyperLogLog+TopN 的方式處理 frequency 問題。具體的做法是這樣的。
HyperLogLog 用於估算出準確的 NDV 值,TopN 用於處理數據傾斜。具體的算法大致如下:
if (topN.get(i) != 0) {

return (long)(topN.get(i) / sampleRate);

}
return (rowcount / cardinality);
HyperLogLog 需要掃描全量數據, TopN 可以通過 Sample 數據構建。

這種數據結構在處理數據的分佈整體較爲平均,僅有少數傾斜嚴重的數據場景中非常優秀。通過 rowcount / cardinality 穩定大多數非傾斜數據,通過 TopN 解決傾斜數據,但 TopN 的 Sample 可能會導致傾斜數據出現較大偏差。

從優化器的需求考慮,能夠通過估算值明顯的區別出傾斜與非傾斜數據,這已經可以滿足 Plan 的選擇需求。

測試

我們基於模擬的隨機數據,對比了 CountMin Sketch 與 HyperLogLog+TopN ,在幾個特定場景下的表現。
主要觀察的數據有以下兩項:

● 最大誤差:估算值與真實值最大差異值
● 誤差平方差:代表誤差範圍的穩定程度

數據場景有以下三種:

bound = 100000
// 均衡:
for (int i = 0; i < size; i++) {
    rs[i] = r.nextInt(bound);
}

// 一半數據傾斜到 1000 個 slot 中
if (r.nextBoolean()) {
    rs[i] = r.nextInt(1000);
} else {
    rs[i] = r.nextInt(bound);
}

// 一半數據傾斜至 100 個 slot 中
if (r.nextBoolean()) {
    rs[i] = r.nextInt(100);
} else {
    rs[i] = r.nextInt(bound);
}

算法初始化參數如下:

● CountMin Sketch 初始化參數 epsOfTotalCount = 0.0001,confidence=0.99,形成了 7*20000 的 long 數組,sketch大約佔1M空間
● TopN 固定 sample 10W 個數據,保留約不超過5000個最大值。 HyperLogLog 精確度在1.04/sqrt(2^16) = 0.004, 空間大約在50K以下

測試的大致結果如下:

5.jpg

6.jpg

在最大誤差中,CountMin 主要來自於均衡數據的膨脹。Hll + TopN 在 10W 的場景最大誤差來自於單一值被估算成了 rowcount/cardinality, 但這個誤差非常小。在100W 和 1000W 的場景,Hll + TopN 的最大誤差遠大於 CountMin,但從整體上判斷,HLL+TopN的誤差平方差相比而方更加穩定,這些誤差主要來自於 TopN 中未記錄的 Skew 數據(未 Sample 到或 TopN 容量不足)。

整體上比較來看,CountMin Sketch 隨數據量增長,針對傾斜數據的估算會更準確,但非傾斜數據的估算會出現較嚴重偏差,這體現在誤差平方差在大數據場景一直保持較高。Hll+TopN 非傾斜數據的估算中非常穩定且準確,傾斜數據的估算會隨數據量增長或 sample 的非隨機性增加而有較嚴重膨脹。

從等值條件基數估算的場景考慮,如果要確保傾斜數據的精確度,應該要選擇 CountMin Sketch,如果要保證非傾斜數據的精確度,傾斜數據只要能識別出就好,採用 Hll+TopN 是更加實用的選擇。

注意以上測試結果僅針對模擬的數據場景。

採集

雖然 CountMin 和 HyperLogLog 回答的問題不同(一個是 frequency, 一個是 ndv ),但本質上都是基於 Sketch 來描述整體數據。基於 Sketch 的算法除了內存佔用小以外,還有個非常大的好處是多個 Sketch 可以合併,並用於描述多分片數據。

大部分統計信息模塊需要收集的數據是不需要考慮多分片帶來的影響的,比如說最大最小值,rowcount,null 值數量,列長度等等。但 ndv 不同,多個分片的 ndv 值無法簡單相加得出。但 HyperLogLog 的 Sketch 數據可以通過多分片合併的方式估算出整體的 ndv 值。CountMin 的 Sketch 也可以通過合併處理。

CountMin 和 HyperLogLog 如果想要較高的精確度,必須要掃描全量的數據,但這會至少給 IO 帶來巨大的影響。 Sketch 類型的算法可以針對各個分片數據建立不同的 Sketch,然後僅掃描有數據變更分片並更新其 Sketch,這樣避免了掃描全量數據的同時,仍然可以在全局得到精確的估算值。
7.jpg

在 Oracle 11g 中,對不活躍的數據分片分成一組統一進行 sketch,這可以極大減少 sketch 佔用的內存空間

結語

The approximate approach is often faster and more efficient

--BY GRAHAM CORMODE

到目前爲止,數據特徵領域已然展開了很長時間的研究,非常多的工具被開發出來。本文主要簡單介紹了其中一部分基於 Sketch 的技術在數據庫等值查詢場景中的區別與影響。

可以看到,這些技術提供了不同場景下解決特定問題的能力,但並非銀彈,謹慎權衡的選擇工具,才能帶來更佳的優化效果。

參考

● Efficient and Scalable Statistics Gathering for Large Databases in Oracle 11g∗
● An Improved Data Stream Summary:The Count-Min Sketch and its Applications
● Every Row Counts: Combining Sketches and Sampling for Accurate Group-By Result Estimates
● HyperLogLog in Practice: Algorithmic Engineering of a State of The Art Cardinality Estimation Algorithm
● Towards Estimation Error Guarantees for Distinct Values
● Data Sketching
● New Sampling-Based Summary Statistics for Improving Approximate Query Answers
● A Comparison of Five Probabilistic View-Size Estimation Techniques in OLAP
● http://content.research.neustar.biz/blog/hll.html

歡迎關注PolarDB-X知乎機構號,閱讀更多技術好文。

原文鏈接:https://click.aliyun.com/m/1000362577/
本文爲阿里雲原創內容,未經允許不得轉載。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章