分區索引是為瞭解決大寬表的儲存和高並發訪問問題而設計的一種新特性。建立搜尋索引時可以指定資料分區策略,服務端自動將資料進行拆分並儲存,查詢資料時系統自動進行分區裁剪。本文介紹資料分區的策略和使用方法。
前提條件
使用情境
Lindorm搜尋索引提供HASH分區和時間分區兩種分區策略,您可以根據以下說明中匹配的業務情境選擇合適的分區策略:
HASH分區
查詢分區裁剪:當業務查詢條件中始終包含某一列的等值查詢時,可以考慮對該列進行HASH分區,以確保相同的值始終落入同一組分區。在查詢過程中,可以實施分區裁剪,僅檢索包含查詢值的特定分區。例如對於裝置表,若查詢條件總是帶有裝置ID,則可以將裝置ID列設定為HASH分區鍵。
分區儲存均衡:HASH分區鍵的選取同時也要考慮到資料分布,如果業務選取的一級分區鍵存在熱點,則可以結合多級HASH分區特性,在一級分區的基礎上將資料更加均勻地散列在幾個分區內。
時間分區
查詢分區裁剪:業務資料具有時間屬性,比如車連網資料、訂單詳情、訊息日誌等,且在查詢的時候經常會使用時間範圍,例如查詢近7天、近一個月的訂單資料,可以使用時間分區特性,根據查詢時間範圍縮小查詢涉及的分區範圍。
單分區儲存上限控制:如果單個索引或分區儲存的資料量過多,一旦資料量增長達到單分區極限,會影響寫入及查詢效能。如果業務索引資料量會一直快速增長,建議結合時間分區策略,控制單個分區內的資料量。
準備工作
使用分區索引前需要建立測試表,語句如下:
CREATE TABLE IF NOT EXISTS search_table (user_id BIGINT, storeId VARCHAR, goodsId VARCHAR, goodsPrice SMALLINT, orderTime BIGINT, info VARCHAR, PRIMARY KEY (user_id asc));HASH分區
Lindorm搜尋索引最多支援三級分區,HASH分區建立後不可改變。HASH分區的文法樣本如下:
一級分區
建立搜尋索引,預設情況下會使用寬表的主鍵進行HASH分區,預設設定的分區數量為搜尋節點數的兩倍。
CREATE INDEX IF NOT EXISTS idx USING SEARCH ON search_table (storeId, goodsId, goodsPrice);建立搜尋索引,指定按照
storeId列進行HASH分區,分區數量為64。其中PARTITION BY hash(storeId)用於指定一級分區鍵為storeId,partitions 64用於指定總分區數為64。CREATE INDEX IF NOT EXISTS idx USING SEARCH ON search_table (storeId, goodsId, goodsPrice) PARTITION BY hash(storeId) PARTITIONS 64;說明業務在選用HASH分區時需要提前根據資料量來評估分區數,一般情況下建議一個分區資料總數在5000萬到1億之間,儲存量在30 GB~50 GB之間。
多級分區
當索引總資料量較多(百億層級以上),且一級分區鍵會產生不均衡資料分布時,建議使用多級分區進行最佳化。
要求寬表引擎為2.8.1及以上版本,搜尋引擎為3.9.22及以上版本。
多級分區暫不支援和時間資料分割函數混用。
建立搜尋索引,指定按照寬表的
storeId和goodsId進行HASH分區,且指定各自分區的加鹽因子(salt_factor)分別為2和4,partitions 64用於指定總分區數為64。CREATE INDEX IF NOT EXISTS idx USING SEARCH ON search_table (storeId, goodsId, goodsPrice) PARTITION BY hash(storeId(salt_factor=2), goodsId(salt_factor=4)) partitions 64;說明分區加鹽因子(salt_factor)應設定為一個較小的整數,用於控制不同分區索引值的散列程度,可根據以下步驟確定總分區數及各分區鍵的加鹽因子:
根據總數量預估總分區數,再選取一個較接近
的數字作為最終的總分區數。例如總資料量為20億,每個分區大致包含的資料量為5,000萬,則大致的分區數量為 40,此時可以選擇作為總分區數。 確定總分區數為
後,建議將多個分區鍵的加鹽因子之和設定為 6,您可以自由分配加鹽因子來控制不同分區鍵的散列範圍。例如:樣本中設定了
storeId的加鹽因子為2,goodsId的加鹽因子為4時,相同storeId,不同goodsId的資料會被分配到總分區的中。若設定 storeId的加鹽因子為3,goodsId的加鹽因子為3,則相同storeId,不同goodsId的資料會被分配到總分區的中。
建立分區索引,指定二級分區鍵為
_id。說明如果一級分區鍵會導致資料分布不均,且業務上沒有合適的二級分區鍵,建議您將
_id指定為二級分區鍵,_id對應寬表主鍵組合。CREATE INDEX IF NOT EXISTS idx USING SEARCH ON search_table (storeId, goodsId, goodsPrice) PARTITION BY hash(storeId(salt_factor=2), _id(salt_factor=4)) partitions 64;
時間分區
對於時間序列資料如訂單資料、訊息日誌等,可以指定時間列,按照時間範圍分區。例如按照周或者月進行分區,同一時間範圍內的資料將會聚集儲存,並且可以自動淘汰舊分區的資料。
建立索引,按照業務的時間列
orderTime分區。RANGE_TIME_PARTITION_START='30'表示從30天前開始建立分區,RANGE_TIME_PARTITION_INTERVAL='7'表示每7天自動分區,RANGE_TIME_PARTITION_TTL='90'表示預設保留90天的分區資料,即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' );重要RANGE_TIME_PARTITION_START參數用於控制分區起始的時間,表示從多少天前開始建立分區。
假設orderTime的最早日期為2021年3月16日,如果業務表需要持續保留,您需要計算從2021年3月16日至建立索引當天間隔的天數,並將其設定為RANGE_TIME_PARTITION_START參數的值。起始時間設定後,若後續新增的orderTime資料小於該值,則新增的記錄會被忽略。
建立索引,按照業務的時間列
orderTime分區,從半年前開始,每1個月自動分區,預設保留半年的分區資料,分區欄位單位設定為秒(s)。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)。
|
RANGE_TIME_PARTITION_MAX_OVERLAP | 否 | 如果寫入的資料時間點是將來的時間,該參數表示最多允許與當前時刻的時間間隔,單位為天。不指定時則表示無限制。 |
RANGE_TIME_PARTITION_FORMAT | 否 | 表示業務指定的時間分區欄位寫入格式,預設為 |