索引選擇與使用最佳實務
Table Store提供二級索引和多元索引兩種索引能力,適用於不同的查詢情境。本文介紹如何選擇索引類型、設計多元索引以及最佳化查詢效能。
索引類型
Table Store的寬表模型按主鍵有序儲存資料,支援主鍵點查和主鍵範圍查詢。當業務需要按屬性列查詢時,主鍵查詢無法滿足需求,而使用過濾器(Filter)在巨量資料量下需要掃描大量資料,效率較低。
查詢效率與底層掃描的資料量正相關,過濾器慢的原因是合格資料過於分散,需要掃描大量資料後才能篩選出結果。Table Store提供兩類索引,分別從兩個思路解決這一問題:
讓合格資料不再分散:二級索引將指定列作為索引表主鍵,通過資料冗餘把合格資料預先排在一起,查詢時直接定位並掃描。
加快篩選速度:多元索引底層建立倒排索引,記錄每個值對應的主鍵集合(Value→主鍵列表),查詢時直接通過倒排索引擷取合格主鍵,加快從海量資料中篩選的效率。
二級索引
二級索引相當於一張索引表,將指定的屬性列作為主鍵重新排序。它與資料表一樣按主鍵有序儲存,查詢能力和資料規模都與資料表相同,區別只在於主鍵不同。查詢時直接通過索引表的主鍵定位元據,效率與資料表主鍵查詢相當。
二級索引分為全域二級索引和本地二級索引,兩者在同步方式、主鍵要求和一致性方面有所不同(強一致指寫入後立即可讀到最新資料,最終一致指寫入後有短暫延遲才能讀到):
|
對比項 |
全域二級索引 |
本地二級索引 |
|
同步方式 |
非同步同步,寫入資料表後自動同步到索引表 |
同步寫入,資料表和索引表同時更新 |
|
第一列主鍵 |
可以是資料表的任意主鍵列或預定義列 |
必須與資料表的分區鍵相同 |
|
資料可見延遲 |
毫秒級 |
即時 |
|
讀取一致性 |
最終一致 |
強一致 |
二級索引適合查詢維度固定的情境,每種查詢維度需要一個獨立的索引。以隱藏檔雜湊值的資料表為例,主鍵列為檔案路徑(FilePath),屬性列為 MD5 和 SHA1:
|
FilePath(主鍵) |
MD5 |
SHA1 |
|
oss://abc/1.txt |
a1b2c3… |
d4e5f6… |
通過主鍵可以查詢檔案對應的雜湊值,但無法通過 MD5 或 SHA1 反查檔案名稱。此時為該表建立一張以 MD5 為主鍵的全域二級索引(SHA1 同理):
|
MD5(主鍵) |
FilePath(主鍵) |
|
a1b2c3… |
oss://abc/1.txt |
為保證索引表主鍵的唯一性,二級索引會自動將資料表的原主鍵列添加到索引表的主鍵中。因此上述索引表的主鍵實際為 MD5 加 FilePath。
多元索引
多元索引是一系列資料結構的組合,底層基於倒排索引、BKD-Tree 等結構,支援多條件組合查詢、全文檢索索引、模糊查詢、地理位置查詢和統計彙總。一個多元索引即可覆蓋多種查詢條件的任意組合,無需為每種組合單獨建立索引。例如訂單表包含 16 個欄位,需要按售貨員、產品類型、價格範圍等任意組合查詢時,只需建立一個多元索引並將查詢欄位添加進去即可。
索引選擇
無需索引的情境
以下情境不需要建立索引:
二級索引與多元索引對比
二級索引和多元索引在查詢靈活度、效能和功能支援上有明顯差異,可根據下表選擇合適的索引類型:
|
對比項 |
二級索引 |
多元索引 |
|
查詢靈活度 |
只能使用建立索引時指定的索引組合查詢,其他組合需建立新的索引表 |
可對索引欄位做任意組合查詢 |
|
查詢效能 |
通過索引鍵定位到對應分區,效能佳 |
需要查詢所有分區(可通過路由鍵最佳化) |
|
大範圍掃描 |
支援,效能與資料表一致 |
支援,但效能低於資料表和二級索引 |
|
資料可見延遲 |
全域二級索引毫秒級,本地二級索引即時 |
秒級 |
|
分詞查詢 |
不支援 |
支援 |
|
地理位置查詢 |
不支援 |
支援 |
|
資料一致性 |
全域二級索引最終一致,本地二級索引強一致 |
最終一致 |
選擇建議:查詢維度固定、追求低延遲或強一致時,選擇二級索引;查詢維度多變,或需要全文檢索索引、模糊查詢、地理位置查詢時,選擇多元索引。
索引組合方案
資料規模很大時,靈活的查詢意味著更高的成本。以萬億行資料為例,僅用資料表(不建索引)成本低但查詢受限,多元索引查詢靈活但費用較高,二級索引成本較低但只適合固定維度查詢。
超大規模資料通常帶有時間屬性(如裝置監控資料、使用者行為資料),可以採用以下組合方案,在查詢靈活性和成本之間取得平衡:
中繼資料表 + 多元索引,全量資料表 + 二級索引或不建索引。中繼資料表是產生資料的主體表(如裝置資訊表、使用者資訊表),資料量相對較小但查詢維度多,適合建立多元索引。全量資料表資料量大但查詢維度固定,使用二級索引或主鍵查詢即可。
熱資料 + 多元索引,冷資料 + 二級索引或不建索引。很多情境只需對熱資料做多維度查詢,對冷資料採取固定維度查詢即可,冷熱分離能提供更高的性價比。多元索引支援資料生命週期(TTL),可以通過多元索引 TTL 區分熱資料和冷資料。更多資訊,請參見多元索引生命週期。
多元索引設計
欄位類型規劃
多元索引中不同類型欄位的底層資料結構不同,選擇合適的欄位類型可以顯著提升查詢效能。建議在向資料表寫入資料時,根據查詢需求提前規劃欄位類型:
|
查詢需求 |
推薦索引類型 |
底層結構 |
樣本欄位 |
|
精確等值、枚舉、多詞查詢 |
Keyword |
FST + 倒排索引 |
Type、Status、UserId |
|
範圍查詢 |
Long |
BKD-Tree |
價格、時間戳記 |
是否將數字欄位轉為字串取決於查詢需求:需要對該欄位做精確匹配(如按 Type、Status、UserId 等值篩選)時,在資料表中儲存為字串類型並索引為 Keyword 類型,才能使用精確查詢(TermQuery)或多詞精確查詢(TermsQuery,類似 SQL 的 IN 操作);需要做範圍查詢時,保留 Long 類型。
如果已使用了不合適的欄位類型且不便修改存量資料,可以使用動態修改Schema功能平滑升級,或使用虛擬列實現欄位類型調整。
索引預排序
如果大多數查詢按相同的排序模式返回結果,可以通過設定預排序節省排序時間。命中資料量越大,預排序帶來的效能提升越明顯。預設情況下,多元索引按資料表的所有主鍵進行預排序。目前僅支援通過 SDK 設定自訂預排序。
索引路由最佳化
預設情況下,多元索引根據資料表的所有主鍵對資料進行雜湊分割,查詢時需要訪問索引引擎的所有分區。如果查詢條件中始終包含某個特定欄位(例如電商情境中的使用者識別碼),可以將該欄位設定為路由鍵,改變資料分布,讓路由索引值相同的資料落在確定的一個或多個分區上。使用路由鍵有以下好處:
顯著減少長尾查詢:未使用路由鍵時每個查詢都會訪問所有分區,整體延遲取決於最慢的分區,單個分區的毛刺或網路卡頓都會拖慢整體請求。
支援更高的 QPS(每秒查詢量):帶路由的請求僅訪問部分分區,沒有讀放大,對叢集資源消耗較少。
規模無上限:路由鍵設計合理時,多元索引的規模無上限。
使用路由鍵的注意事項:
路由鍵的值應盡量多樣,同一個路由鍵下的資料量不要太多(例如不超過 1 億行)。如果單個路由鍵下資料過多,可以將多個不變的欄位拼接為路由鍵。
設定路由鍵後,如果查詢時不指定路由鍵,會訪問所有分區,但不影響查詢結果的完整性。
查詢 QPS 不高或資料量小於 2 億行時,無需使用路由最佳化。
邏輯欄位與物理欄位對應
當系統中有大量使用者、每個使用者的列名各不相同時,所有使用者的個人化欄位加起來會遠超多元索引的最大欄位數限制。此時可以用一批固定的物理欄位讓所有使用者複用。
複用原理:不同使用者的資料存放區在不同行,同一個物理欄位在不同使用者的行中可以承載不同的邏輯欄位。例如物理欄位 keyword_1 在使用者 1 的行中儲存欄位 a,在使用者 2 的行中儲存欄位 b。再通過一張 meta 映射表記錄每個使用者的欄位對應關係即可。
假設每個使用者最多使用 10 個 Keyword 類型的索引欄位,設計步驟如下:
索引設計:按單個使用者需要的欄位數建立固定的物理欄位。例如每個使用者最多 10 個欄位,則建立
keyword_1至keyword_10(如需 Long 類型再加long_1至long_10),以及其他業務必要的非個人化欄位。無論有多少使用者,多元索引只需要這一批物理欄位。準備 meta 映射表:記錄每個使用者的邏輯欄位名到物理欄位名的映射。例如使用者 1 的欄位 a、b、c 分別映射為
keyword_1、keyword_2、keyword_3;使用者 2 的欄位 b、c、d 分別映射為keyword_1、keyword_2、keyword_3。兩個使用者複用了相同的物理欄位,但因為資料在不同行,互不影響。映射表資料量不大時,建議緩衝到記憶體中。按映射讀寫資料:寫入時根據映射表將使用者的邏輯欄位值寫入對應的物理欄位;查詢時根據映射錶轉換查詢條件,例如使用者 2 查詢 b=4 且 d=5,轉化為
keyword_1=4 且keyword_3=5。
多元索引查詢最佳化
選擇合適的查詢方式
多元索引提供多種查詢方式,根據查詢需求選擇合適的方式可以獲得更好的效能:
|
查詢需求 |
推薦方式 |
說明 |
|
精確等值查詢 |
精確查詢(TermQuery) |
Keyword 類型欄位使用此方式。不要誤用匹配查詢(MatchQuery),否則會多一道分詞處理,效能較差。 |
|
分詞文本全文檢索索引 |
匹配查詢(MatchQuery)/ 短語匹配查詢(MatchPhraseQuery) |
用於分詞(將文本切分為詞語)的 Text 類型欄位。 |
|
任意子串模糊比對( |
模糊分詞 + 短語匹配查詢(MatchPhraseQuery) |
比萬用字元查詢(WildcardQuery)效能更好。 |
簡化查詢條件
如果查詢條件過多、嵌套過深或 TermsQuery 中的元素過多,查詢延遲可能會偏高。精簡查詢條件,只保留必要的篩選項。服務端會自動改寫並最佳化查詢,一般無需額外關注;如果查詢延遲偏高,請聯絡Table Store支援人員最佳化查詢。
深度翻頁與 Token 編碼
深度翻頁推薦使用 Token 翻頁方式。持久化儲存 Token(byte[] 類型)時,必須使用 Base 64 編碼將其轉換為字串。直接使用 new String(token) 進行字串編碼會導致 Token 內容丟失。