TiDB 的“聚簇因子” -- 從 cop task 到 shard_row_id_bits

語言: CN / TW / HK

作者: pepezzzz 原文來源:https://tidb.net/blog/086d700a

引言

Oracle 的聚簇因子:

表中建立了索引的資料排序優良度的一個度量值;向優化器表明了具有同樣索引值的資料行是不是存放在同一個或連續的一系列資料塊中,或者資料行是否被分散存放在表的多個數據塊中。簡單地說,Oracle 資料庫的聚簇因子資訊,能反映出索引範圍掃的回表成本。# 從案例看 cop task## 案例1下圖是一個 SQL 的執行計劃,選中行是 IndexLookUp 運算元回表後過濾運算元。image.png從右側 Operator Info 欄中的可見,416 行的索引回表過濾需要使用 26 的 cop task,可以簡單地認為 416 行表資料處於 26 個 region 中。經過資料 “按序” 的匯出和匯入:a. dumpling --sql “select * from a order by cus_id” -F 100MiB --output-filename-template …b. tidb-lightning下圖是 SQL 的新執行計劃,執行計劃完全一樣,效率有較大的提升。從右側 Operator Info 欄中的可見,416 行的索引回表過濾僅需要使用 4 的 cop task,可以簡單地認為 416 行表資料僅處於 4 個 不同 region 中,相關的資料“聚集”後,回表的開銷降低了,網路的請求變快了,高併發情況下尤為明顯。## 案例2單表 500 萬的資料刪除主鍵後進行“翻數”,重複插入 200 次,得到一個 10 億記錄的表。查詢 SQL:select * from t where col1='1' ,col1 列上有二級索引。進行壓測時,報:Coprocessor task terminated due to exceeding the deadline。可以認為,由於 10 億記錄的表通過以上的翻數操作得到,資料處於非常 “均勻” 的分散,單條語句的二級索引回表的 cop task 固定為 200,在高併發情況下,極容易觸發以上的報錯資訊。通過相同的“資料整理”步驟,單語句 SQL 效率提升較大。## Region 與 cop taskRegion 是 TiDB 中計算、儲存、排程的單元。計算單元的含義,大致可以理解為,cop 請求也會以 region 為單位進行分發。上述案例中,由於資料較為分散,即相同索引值的資料分佈在較多的 region 中,會導致單條 SQL 語句的 cop task 變多,影響語句的執行效率,乃至於觸發 tikv 的報錯。在目前 TiDB 的統計資訊設計中,沒有類似於 Oracle 的聚簇因子的概念,但是實際上仍受資料 “聚簇” 效果的影響。之前常見於 Oracle 的資料維護操作,對 TiDB 也有相同效果。壓測和生產中的高頻語句,需要注意相關資料寫入分佈的行為和影響。# shard_row_id_bitsTiDB v6.5 之前,預設情況下,非整數主鍵、沒有主鍵的表或者建表時顯式指定 nonclustered 非聚簇的表,TiDB 會使用一個隱式的自增 rowid。大量執行 INSERT 插入語句時,由於 rowid 自增分配,會把資料集中寫入單個 Region,造成寫入熱點。通過設定 SHARD_ROW_ID_BITS,可以把 rowid 打散寫入多個不同的 Region,緩解寫入熱點問題。它的使用效果如下圖:image.png隱式的自增 rowid 會因為左側 shard bits 的翻轉,會連續生成 “跳躍” 的 rowid,如 0000...0000,0001...0001,0010...0010,0011...0011,0000...0100,0001...0101,0010...0110 等,得到連續插入資料時,rowid 不連續的效果,規避了寫入單個 Region 熱點的問題。從上圖中,可見 SHARD_ROW_ID_BITS 代表的是 “翻轉位數”,2 的冪代表實際 kv map 中的 rowid 寫入點數量,即 SHARD_ROW_ID_BITS = 4 表示 16 個分片/ Region。但是,SHARD_ROW_ID_BITS 配置同時會帶來寫入資料不聚集的問題,從下圖中可以看出,同一時間寫入的資料,由於 SHARD_ROW_ID_BITS = 2,分佈在四個不同的 Region 上。如果語句條件是根據時間進行範圍掃,TableRowidScan 運算元的 cop task 會增加 3 倍。image.png在生產實踐中,關於 SHARD_ROW_ID_BITS 個人的建議是:通常配置為 2寫入壓力大的情況可以配置為 3不要超過 4另外,如果 tikv 例項的數量較小,不需要配置太大的 SHARD_ROW_ID_BITS。# 結論實際上,TiDB 的“聚簇因子”存在並影響索引讀取的效率。在壓測和生產實踐過程中,需要關注回表資料和 cop task 的大概比例關係。## 題外話 merge_option=deny表屬性是 TiDB 從 5.3.0 版本開始引入的新特性。如果建表時指定 shard_row_id_bits 時,希望建表時就均勻切分 Region,可以考慮配合 PRE_SPLIT_REGIONS 一起使用,用來在建表成功後就開始預均勻切分 2^(PRE_SPLIT_REGIONS) 個 Region。但由於新建表或分割槽的分裂操作實際產生的是空 Region,如果分裂打散操作距離寫入存在一定時間間隔,則 Region 可能會被合併,從而導致無法真正規避寫入熱點問題。此時可以為表或分割槽新增 merge_option 屬性,設定為 deny 來解決問題。- 禁止屬於某個表的 Region 被合併

ALTER TABLE t ATTRIBUTES 'merge_option=deny';
```#