索引選擇與使用最佳實務

更新時間:
Copy as MD

Table Store提供二級索引和多元索引兩種索引能力,適用於不同的查詢情境。本文介紹如何選擇索引類型、設計多元索引以及最佳化查詢效能。

索引類型

Table Store的寬表模型按主鍵有序儲存資料,支援主鍵點查和主鍵範圍查詢。當業務需要按屬性列查詢時,主鍵查詢無法滿足需求,而使用過濾器(Filter)在巨量資料量下需要掃描大量資料,效率較低。

查詢效率與底層掃描的資料量正相關,過濾器慢的原因是合格資料過於分散,需要掃描大量資料後才能篩選出結果。Table Store提供兩類索引,分別從兩個思路解決這一問題:

  • 讓合格資料不再分散:二級索引將指定列作為索引表主鍵,通過資料冗餘把合格資料預先排在一起,查詢時直接定位並掃描。

二級索引

二級索引相當於一張索引表,將指定的屬性列作為主鍵重新排序。它與資料表一樣按主鍵有序儲存,查詢能力和資料規模都與資料表相同,區別只在於主鍵不同。查詢時直接通過索引表的主鍵定位元據,效率與資料表主鍵查詢相當。

二級索引分為全域二級索引和本地二級索引,兩者在同步方式、主鍵要求和一致性方面有所不同(強一致指寫入後立即可讀到最新資料,最終一致指寫入後有短暫延遲才能讀到):

對比項

全域二級索引

本地二級索引

同步方式

非同步同步,寫入資料表後自動同步到索引表

同步寫入,資料表和索引表同時更新

第一列主鍵

可以是資料表的任意主鍵列或預定義列

必須與資料表的分區鍵相同

資料可見延遲

毫秒級

即時

讀取一致性

最終一致

強一致

二級索引適合查詢維度固定的情境,每種查詢維度需要一個獨立的索引。以隱藏檔雜湊值的資料表為例,主鍵列為檔案路徑(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 個欄位,需要按售貨員、產品類型、價格範圍等任意組合查詢時,只需建立一個多元索引並將查詢欄位添加進去即可。

索引選擇

無需索引的情境

以下情境不需要建立索引:

  • 主鍵查詢和主鍵範圍查詢已滿足業務需求。

  • 對某個範圍內的資料進行篩選,且範圍內資料量不大或查詢頻率不高時,使用過濾器(Filter)即可。更多資訊,請參見過濾器

  • 複雜查詢執行頻率低且對延遲不敏感時,使用 SQL 查詢。更多資訊,請參見SQL查詢

二級索引與多元索引對比

二級索引和多元索引在查詢靈活度、效能和功能支援上有明顯差異,可根據下表選擇合適的索引類型:

對比項

二級索引

多元索引

查詢靈活度

只能使用建立索引時指定的索引組合查詢,其他組合需建立新的索引表

可對索引欄位做任意組合查詢

查詢效能

通過索引鍵定位到對應分區,效能佳

需要查詢所有分區(可通過路由鍵最佳化)

大範圍掃描

支援,效能與資料表一致

支援,但效能低於資料表和二級索引

資料可見延遲

全域二級索引毫秒級,本地二級索引即時

秒級

分詞查詢

不支援

支援

地理位置查詢

不支援

支援

資料一致性

全域二級索引最終一致,本地二級索引強一致

最終一致

選擇建議:查詢維度固定、追求低延遲或強一致時,選擇二級索引;查詢維度多變,或需要全文檢索索引、模糊查詢、地理位置查詢時,選擇多元索引。

索引組合方案

資料規模很大時,靈活的查詢意味著更高的成本。以萬億行資料為例,僅用資料表(不建索引)成本低但查詢受限,多元索引查詢靈活但費用較高,二級索引成本較低但只適合固定維度查詢。

超大規模資料通常帶有時間屬性(如裝置監控資料、使用者行為資料),可以採用以下組合方案,在查詢靈活性和成本之間取得平衡:

  • 中繼資料表 + 多元索引,全量資料表 + 二級索引或不建索引。中繼資料表是產生資料的主體表(如裝置資訊表、使用者資訊表),資料量相對較小但查詢維度多,適合建立多元索引。全量資料表資料量大但查詢維度固定,使用二級索引或主鍵查詢即可。

  • 熱資料 + 多元索引,冷資料 + 二級索引或不建索引。很多情境只需對熱資料做多維度查詢,對冷資料採取固定維度查詢即可,冷熱分離能提供更高的性價比。多元索引支援資料生命週期(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 類型的索引欄位,設計步驟如下:

  1. 索引設計:按單個使用者需要的欄位數建立固定的物理欄位。例如每個使用者最多 10 個欄位,則建立 keyword_1keyword_10(如需 Long 類型再加 long_1long_10),以及其他業務必要的非個人化欄位。無論有多少使用者,多元索引只需要這一批物理欄位。

  2. 準備 meta 映射表:記錄每個使用者的邏輯欄位名到物理欄位名的映射。例如使用者 1 的欄位 a、b、c 分別映射為 keyword_1keyword_2keyword_3;使用者 2 的欄位 b、c、d 分別映射為 keyword_1keyword_2keyword_3。兩個使用者複用了相同的物理欄位,但因為資料在不同行,互不影響。映射表資料量不大時,建議緩衝到記憶體中。

  3. 按映射讀寫資料:寫入時根據映射表將使用者的邏輯欄位值寫入對應的物理欄位;查詢時根據映射錶轉換查詢條件,例如使用者 2 查詢 b=4 且 d=5,轉化為 keyword_1=4 且 keyword_3=5。

多元索引查詢最佳化

選擇合適的查詢方式

多元索引提供多種查詢方式,根據查詢需求選擇合適的方式可以獲得更好的效能:

查詢需求

推薦方式

說明

精確等值查詢

精確查詢(TermQuery)

Keyword 類型欄位使用此方式。不要誤用匹配查詢(MatchQuery),否則會多一道分詞處理,效能較差。

分詞文本全文檢索索引

匹配查詢(MatchQuery)/ 短語匹配查詢(MatchPhraseQuery)

用於分詞(將文本切分為詞語)的 Text 類型欄位。

任意子串模糊比對(*word*

模糊分詞 + 短語匹配查詢(MatchPhraseQuery)

比萬用字元查詢(WildcardQuery)效能更好。

簡化查詢條件

如果查詢條件過多、嵌套過深或 TermsQuery 中的元素過多,查詢延遲可能會偏高。精簡查詢條件,只保留必要的篩選項。服務端會自動改寫並最佳化查詢,一般無需額外關注;如果查詢延遲偏高,請聯絡Table Store支援人員最佳化查詢。

深度翻頁與 Token 編碼

深度翻頁推薦使用 Token 翻頁方式。持久化儲存 Token(byte[] 類型)時,必須使用 Base 64 編碼將其轉換為字串。直接使用 new String(token) 進行字串編碼會導致 Token 內容丟失。