列存索引創(chuàng)建指南
本文介紹如何根據(jù)業(yè)務(wù)場景為目標表創(chuàng)建查詢性能更優(yōu)的列存索引(CCI)。
適用場景
列存索引是基于日志節(jié)點(CDC)鏈路異步構(gòu)建而成,可以保證數(shù)據(jù)的查詢一致性,但由于主實例向列存只讀實例同步數(shù)據(jù)存在秒級延遲,因此對于實時性要求極高的場景,不建議使用CCI。
混合負載場景或需要給復(fù)雜查詢加速的場景。
說明列存索引可以有效提升復(fù)雜查詢(AP)的性能。
冷數(shù)據(jù)歸檔場景。
說明因為列存的讀節(jié)點(CN節(jié)點)可以通過存儲在OSS中的列存索引數(shù)據(jù)來獲取元數(shù)據(jù),所以您可以把冷數(shù)據(jù)使用列存索引技術(shù)轉(zhuǎn)儲至OSS,以降低存儲成本。更多信息,請參見冷數(shù)據(jù)歸檔(TTL)。
歷史快照保存和查詢場景。
說明列存索引可以看作不會過期的歷史數(shù)據(jù)副本,可以保存歷史快照,并提供歷史快照查詢,常用于審計和備份業(yè)務(wù)。
ETL場景。
說明列存索引可以看作是主實例的數(shù)據(jù)副本,您可以連接列存只讀實例,使用其中數(shù)據(jù)提供數(shù)據(jù)提取、轉(zhuǎn)換、加載(Extract Transform Load,ETL)服務(wù),并將數(shù)據(jù)庫的數(shù)據(jù)轉(zhuǎn)儲到其他數(shù)據(jù)系統(tǒng)。
分區(qū)表
常用分區(qū)類型介紹
列存索引的分區(qū)是一種數(shù)據(jù)庫設(shè)計技術(shù)中的概念,主要用于大型表的數(shù)據(jù)分片或分割,以提高查詢性能和管理大量數(shù)據(jù)的效率。列存索引的分區(qū)策略語法如下:
PARTITION BY
HASH({column_name | partition_func(column_name)})
| KEY(column_list)
| RANGE({column_name | partition_func(column_name)})
| RANGE COLUMNS(column_list)
| LIST({column_name | partition_func(column_name)})
| LIST COLUMNS(column_list)} }
范圍分區(qū)(RANGE):根據(jù)某一列的取值范圍劃分數(shù)據(jù)。例如:包含歷史銷售記錄的表,根據(jù)銷售年份進行范圍分區(qū),不同年份的數(shù)據(jù)會被存儲在不同的分區(qū)中。
列表分區(qū)(LIST):根據(jù)列值是否屬于某個預(yù)定義列表劃分數(shù)據(jù),常用于SAAS場景。例如:用戶數(shù)據(jù)表可以根據(jù)用戶所在國家進行列表分區(qū),不同國家的用戶數(shù)據(jù)會被分別存儲在對應(yīng)的分區(qū)中。
哈希分區(qū)(HASH/KEY):根據(jù)列值的哈希值劃分數(shù)據(jù),可以保證數(shù)據(jù)均勻分布。適用于無法預(yù)測的數(shù)據(jù)分布情況,或者需要均勻分布數(shù)據(jù)的情況。
更多信息,請參見分區(qū)類型。
設(shè)置分區(qū)數(shù)的原則
分區(qū)數(shù)理論上與表的數(shù)量以及列存只讀實例的規(guī)格有關(guān)。如果不明確指定分區(qū)數(shù),則默認分區(qū)數(shù)為16。然而,通常不建議使用默認的分區(qū)數(shù)。一般遵循的原則是:列存索引的分區(qū)數(shù)的建議值為計算節(jié)點的個數(shù)*計算節(jié)點核數(shù)
。考慮到未來數(shù)據(jù)增長的潛力,最終確定的分區(qū)數(shù)也可以高于這個建議值。
多表關(guān)聯(lián)操作時,為了減少需要數(shù)據(jù)重新分布的數(shù)據(jù)量,建議同一個實例中涉及的表,分區(qū)數(shù)保持一致。
選擇分區(qū)策略的原則
因為列存索引主要是為了提升AP類查詢的性能,且該類查詢大多是聚合和關(guān)聯(lián)查詢,所以為了發(fā)揮列存并行掃描和查詢優(yōu)勢,建議采用哈希分區(qū)。
查詢條件有明確的時間含義,這種情況下建議將日期、時間類型的字段作為二級分區(qū),除了該場景,其他場景如非必要請不要為列存索引創(chuàng)建二級分區(qū)。更多信息,請參見二級分區(qū)。
沒有明確的范圍查詢,不建議使用范圍分區(qū);沒有基于某個預(yù)定義列表值的查詢,不建議使用列表分區(qū);即便查詢具備上述特征,也應(yīng)優(yōu)先考慮依賴行存來滿足上述查詢。
業(yè)務(wù)上依托CCI實現(xiàn)冷數(shù)據(jù)歸檔,建議使用時間列進行范圍分區(qū)。
選擇分區(qū)鍵的原則
選擇值分布均勻的字段作為分區(qū)鍵,例如交易ID、設(shè)備ID、用戶ID或者自增列作為分區(qū)鍵。
說明盡量不要選擇日期、時間和時間戳類型的字段作為分區(qū)鍵,寫入時容易發(fā)生傾斜影響寫入性能,且多數(shù)查詢通常是限定了日期或者時間段,如:查詢最近一天或者一個月的數(shù)據(jù),可能會導(dǎo)致要查詢的數(shù)據(jù)只存在于一個節(jié)點上,無法充分利用分布式數(shù)據(jù)庫中所有節(jié)點的處理能力。這種情況下可以考慮將日期、時間類型的字段建議作為二級分區(qū)來考慮。
盡可能將需要
JOIN
和GROUP BY
的字段作為分區(qū)鍵,可以有效減少數(shù)據(jù)重分布。例如,需要按照顧客維度查看歷史訂單信息,可以選擇顧客ID作為分區(qū)鍵。盡可能選擇頻繁出現(xiàn)在非范圍查詢條件中的字段作為分區(qū)鍵,從而實現(xiàn)按分區(qū)鍵進行數(shù)據(jù)裁剪。
每張表只能選擇一個分區(qū)鍵,一個分區(qū)鍵可以包含一個或多個字段。分區(qū)鍵的字段越少就越在復(fù)雜的查詢場景中具備通用性。
在創(chuàng)建表時,如果沒有指定分區(qū)鍵,系統(tǒng)會將主鍵作為分區(qū)鍵;對于沒有顯式定義主鍵的表,系統(tǒng)會將隱式主鍵作為分區(qū)鍵。
創(chuàng)建列存索引后,可以通過執(zhí)行
check columnar partition db_name.tbl_name
命令來查看各個分區(qū)的數(shù)據(jù)量,以此判斷所選分區(qū)鍵是否合適,是否存在數(shù)據(jù)傾斜的情況。
排序鍵
排序鍵介紹
列存索引的排序鍵定義了數(shù)據(jù)在索引文件中的排序方式,即數(shù)據(jù)按照該列有序存儲。每個列數(shù)據(jù)塊的元數(shù)據(jù)包含了該列數(shù)據(jù)塊中所有數(shù)據(jù)的最小值和最大值等信息。在查詢數(shù)據(jù)時,通常需要遍歷指定列的所有列數(shù)據(jù)塊。啟用Pruner功能后,會根據(jù)查詢條件與元數(shù)據(jù)信息將所有列數(shù)據(jù)塊分為三類:相關(guān)、可能相關(guān)和不相關(guān)。在讀取數(shù)據(jù)時,僅考慮相關(guān)和可能相關(guān)的列數(shù)據(jù)塊。由于列數(shù)據(jù)塊可以有不同的排列順序,形成不同的組合,Pruner功能也會產(chǎn)生不同的過濾效果。因此,您可以改變查詢條件來調(diào)整列數(shù)據(jù)塊的排列順序,以進一步提高查詢性能。
選擇排序鍵的原則
數(shù)據(jù)表被頻繁使用范圍查詢的場景下,建議使用該范圍條件的列作為排序鍵。
使用分頁查詢的場景下,建議使用
ORDER BY
列作為排序鍵其他場景下,建議使用分區(qū)鍵作為排序鍵。
字典編碼列
字典編碼列介紹
字典編碼可以將字符串的比較轉(zhuǎn)換為數(shù)字的比較,從而提升字符串列的GROUP BY、FILTER等查詢的性能,并提升數(shù)據(jù)的壓縮比,進一步降低存儲成本。在PolarDB-X中,可以在創(chuàng)建列存索引時對指定字段進行字典編碼,即為這些字段的值構(gòu)建字典映射。示例:
# 顯示指定字典列
DICTIONARY_COLUMNS='col1,col2';
# 顯式指定字典列創(chuàng)建列存索引
CREATE CLUSTERED COLUMNAR INDEX `cc_i_seller` ON t_order (`seller_id`) partition by hash(`order_id`) partitions 16
dictionary_columns='order_id,seller_id';
選擇字典編碼列的原則
建議將基數(shù)較小的字符列設(shè)置為字典編碼列,例如該列代表性別、地區(qū)等具備有限種類的分類信息。
不建議將所有的字符列都設(shè)置為字典編碼列,因為這樣做會帶來額外的編碼、解碼開銷。
對于列基數(shù)較小的字符列使用字典編碼不僅可以實現(xiàn)數(shù)據(jù)壓縮,減少存儲空間的占用,還能優(yōu)化查詢性能。然而,在分布式數(shù)據(jù)庫查詢中,會涉及到字典的解析和合并操作,這會引入額外的開銷。因此,在查詢過程中,基于字典的查詢默認是關(guān)閉的。如果需要啟用,需要將ENABLE_COLUMNAR_SLICE_DICT
參數(shù)設(shè)置為TRUE
。
常見問題
在集群變配,是否會對分區(qū)數(shù)產(chǎn)生影響?
答:不會產(chǎn)生影響。
列存索引是否支持修改分區(qū)鍵、排序鍵、分區(qū)數(shù)、字典編碼列?
答:不支持。如有需要,請您刪除并重建該列存索引。
創(chuàng)建列存索引,需要購買列存只讀實例嗎?
答:可以直接在主實例上創(chuàng)建列存索引,如果要查詢列存索引數(shù)據(jù)建議購買列存只讀實例。