分區索引是為了解決大寬表的存儲和高并發訪問問題而設計的一種新特性。創建搜索索引時可以指定數據分區策略,服務端自動將數據進行拆分并存儲,查詢數據時系統自動進行分區裁剪。本文介紹數據分區的策略和使用方法。
前提條件
已開通云原生多模數據庫 Lindorm實例的搜索索引服務,具體操作請參見開通搜索索引。
已通過Lindorm-cli連接Lindorm寬表引擎,具體操作請參見通過Lindorm-cli連接并使用寬表引擎。
使用場景
業務數據具有時間屬性,例如車聯網數據、訂單詳情、消息日志等。
業務數據有明顯的聚類特性,例如商家數據表以商家ID為聚類,查詢條件中包括商家ID。IoT設備數據表以設備ID為聚類,查詢條件中包括設備ID。
數據分區策略
準備工作
使用分區索引前需要創建測試表,語句如下:
CREATE TABLE IF NOT EXISTS search_table (user_id bigint, storeId varchar, goodsId varchar, goodsPrice smallint, orderTime bigint, info varchar, constraint primary key (user_id asc));
HASH分區
HASH分區將數據進行散列存儲,從而避免出現數據的熱點問題。在數據寫入量較大的場景中可以很好地實現數據均衡。搜索索引默認按照Lindorm寬表的主鍵進行HASH分區,同時也支持自定義分區鍵。
HASH分區的語法示例如下:
創建搜索索引,默認按照Lindorm寬表的主鍵進行HASH分區,默認設置的分區數量為搜索節點數乘以2。
CREATE INDEX IF NOT EXISTS idx USING SEARCH ON search_table (storeId, goodsId, goodsPrice);
創建搜索索引,按照Lindorm寬表的storeId列進行HASH分區(即一級HASH分區),分區數量為64。
CREATE INDEX IF NOT EXISTS idx USING SEARCH ON search_table (storeId, goodsId, goodsPrice) partition by hash(storeId) partitions 64;
重要業務查詢時,如果多數情況下會攜帶某個列作為過濾條件,可將該列設置為自定義分區鍵。
對于適用自定義分區鍵的場景,可根據實際業務情況將分區數量partitions設置大一些。如果不確定具體數值,可先設置64作為初始測試值。
對Lindorm寬表的某一列進行HASH分區(即一級HASH分區)時,如果自定義的分區鍵(也就是Lindorm寬表的某一列)存在熱點問題,如一個storeId列下最多可能匹配到10%以上的數據,那么可能導致大量數據寫入同一個分區中,影響查詢和寫入性能。建議使用多級HASH分區(高級用法),對Lindorm寬表的多個列組合進行HASH分區(即二級HASH分區或者三級HASH分區)。
- 自定義分區鍵的值有以下限制:
- 分區鍵值不可更改。
- 分區鍵值不能為空。
時間范圍分區
對于一些時間序列的數據,可以按照時間范圍分區,例如按照周或者月進行分區,同一時間范圍內的數據將會聚集存儲,并且可以自動淘汰舊分區的數據。
按照時間范圍分區的語法示例如下:
創建索引,按照業務的時間列orderTime分區,從30天前開始,每7天自動分區,默認保留90天的分區數據。
CREATE INDEX idx USING SEARCH ON search_table (storeId, goodsId, goodsPrice, orderTime) partition by range time(orderTime) partitions 4 with (indexState=ACTIVE, RANGE_TIME_PARTITION_START='30', RANGE_TIME_PARTITION_INTERVAL='7', RANGE_TIME_PARTITION_TTL='90');
創建索引,按照業務的時間列orderTime分區,從半年前開始,每1個月自動分區,默認保留半年的分區數據,分區字段單位設置為秒。
CREATE INDEX idx USING SEARCH ON search_table (storeId, goodsId, goodsPrice, orderTime) partition by range time(orderTime) partitions 4 with (indexState=ACTIVE, RANGE_TIME_PARTITION_START='180', RANGE_TIME_PARTITION_INTERVAL='30', RANGE_TIME_PARTITION_TTL='180', RANGE_TIME_PARTITION_FIELD_TIMEUNIT='s');
按照時間范圍分區的參數說明如下表:
參數 | 是否必選 | 說明 |
RANGE_TIME_PARTITION_START | 是 | 表示創建索引操作前多少天開始創建分區。適用于有歷史數據的場景,如果歷史數據的時間戳比開始分區的時間還要小,則會報錯。 |
RANGE_TIME_PARTITION_INTERVAL | 是 | 表示間隔多少天創建新分區,例如 |
RANGE_TIME_PARTITION_TTL | 否 | 表示保留多少天的分區數據,例如 |
RANGE_TIME_PARTITION_FIELD_TIMEUNIT | 否 | 表示業務指定的時間分區字段單位,默認單位為毫秒(ms)。
|
多級HASH分區(高級用法)
按照Lindorm寬表的storeId列和goodsId列組合進行二級HASH分區,加鹽因子(salt_factor)為4,分區數量為64。
//相同storeId,不同goodsId的數據會被打散到4個分區中去
CREATE SEARCH INDEX idx ON search_table (storeId, goodsId, goodsPrice) partition by hash(storeId(salt_factor=4),goodsId) partitions 64;
- 加鹽因子(
salt_factor
)是進一步散列相同storeId列值的數據,通常設置為一個較小的數值,并且數值與分區數量是兩倍的數量關系。如果分區數量為16,當salt_factor大于4時,則無法散列數據。加鹽因子的其他值表示如下:salt_factor=1
:表示相同storeId列的數據,不同goodsId列的數據會被散列到分區總數量的一半中。salt_factor=2
:表示相同storeId列的數據,不同goodsId列的數據會被散列到分區總數量的1/4中。salt_factor=3
:表示相同storeId列的數據,不同goodsId列的數據會被散列到分區總數量的1/8中。
- 多級HASH分區(二級HASH分區或者三級HASH分區)除了可以散列數據,在查詢數據場景中也大大提高了查詢效率。例如在上述二級HASH分區中,查詢數據時同時輸入storeId列和goodsId列的過濾信息會確定在一個分區中進行數據檢索,減少數據的掃描范圍從而提高查詢效率。
- 使用二級HASH分區時,一級分區鍵(Lindorm搜索表的第一列即storeId列)必須設置加鹽因子。使用三級HASH分區時,一級分區鍵和二級分區鍵都必須設置加鹽因子。
- 自定義分區鍵的值有以下限制:
- 分區鍵值不可更改。
- 分區鍵值不能為空。