全部產品
Search
文件中心

Lindorm:二級索引

更新時間:Aug 07, 2024

Lindorm寬表支援Tabular模型下的二級索引功能,此功能在非主鍵匹配的查詢情境下,可以降低應用的開發複雜性、保證資料的一致性和提高寫入效率。本文介紹Lindorm Tabular模型下二級索引的基本特性和使用樣本。

背景資訊

對於Lindorm Tabular模型,Lindorm寬表有表結構且表對應的列有類型預定義的。Lindorm原生二級索引功能在阿里雲應用多年,經歷了多次雙11的考驗,更加適用於解決海量資料的全域索引。Lindorm與Phoenix在索引情境下的效能對比如下圖所示。

  • 讀寫RT對比投影片1.PNG

    產品

    單行寫RT

    單行讀RT

    批量寫100行RT

    Lindorm

    1.409

    0.492

    10.447

    開源Phoenix

    2.264

    2.594

    26.224

    可以看出,在索引情境下Lindorm進行讀寫操作耗時更少。單行寫RT用時約為開源Phoenix的62%,單行讀RT用時約為開源Phoenix的19%,批量寫100行RT約為開源Phoenix的40%

  • 寫吞吐對比投影片2.PNG

    產品

    BatchPut

    Put

    Get

    Scan

    Lindorm

    198174

    73214

    156372

    1283451

    開源Phoenix

    56923

    33156

    25910

    224085

    可以看出,在索引情境下Lindorm的BatchPut約為開源Phoenix的3.5倍,Put約為開源Phoenix的2.2倍,Get約為開源Phoenix的6倍,Scan約為開源Phoenix的5.7倍

特性介紹

Lindorm二級索引支援為單表建多個索引,每個索引在物理上映射為一張資料表,與主表相互獨立,每個索引有不同的儲存策略(如採用不同的壓縮演算法、冷熱分離策略)等屬性。寫主表時,Lindorm會自動更新所有索引表,並確保主表和索引表資料的一致性。讀資料時,您只需針對主表發起查詢,Lindorm會根據WHERE條件和SCHEMA自動選擇合適的索引(包括主表)執行查詢操作(支援HINT來幹預最佳化器行為)。Lindorm二級索引的基本特性如下。

  • 支援單個主表建多個索引。

  • 支援複合式索引(單列和多列)。

  • 支援冗餘索引,全冗餘索引可自動冗餘主表新增的列。

  • 查詢最佳化:根據WHERE語句自動選擇索引,支援HINT來幹預最佳化器的選擇。

  • Online Schema Change:索引變更不影響主表的正常讀寫,可以隨時新增、刪除、更新索引。

  • 支援資料有效期間(簡稱:TTL):索引表自動繼承主表的TTL設定,主表和索引表資料同時到期。

  • 支援動態列:支援寫入動態列和冗餘動態列。

  • 支援自訂資料版本:自訂時間戳記後自動寫入資料。

使用要求

基本概念

  • 強一致性:是指主表和索引表的資料一致性。為了滿足資料一致性的需求,最大程度減少二級索引的額外開銷,提升高吞吐的寫入能力,Lindorm二級索引在強一致性中具有如下約束。

    • 不支援快照隔離性。在資料寫入過程中不保證同時可見,但是返回用戶端寫入成功後主表和索引表資料可見。

    • 在返回用戶端逾時或IO出錯情況下,該資料在主表和索引表中不保證可見,但最終主表和索引表資料會保持一致。

  • 可選的索引組織成本:在主表有一個索引的情況下,寫放大有四次操作(讀主表,刪除索引老資料,寫索引,寫主表),會大大增加維護索引的成本。但不是所有情境都會產生寫放大,比如日誌情境只有資料插入沒有更新操作,此時索引表不存在老資料,只需要做寫索引和寫主表操作。所以Lindorm提出了Mutability的概念。Mutability是指對主表的寫入模式進行分類,並以此組織索引資料,針對不同的需求實現最低的索引組織成本。Mutability分類和描述如下表所示。Mutability屬性需要在建立表或修改表時通過Table_Options參數進行設定,具體操作,請參見CREATE TABLE文法介紹

    Mutability分類

    約束

    操作成本

    操作說明

    無索引

    無。

    1

    沒有索引的情況下,直接寫主表,為1次操作。

    IMMUTABLE

    整行寫入,不可更新或刪除。

    2

    寫主表,寫索引表。所有情境中成本最低,效能最好。

    IMMUTABLE_ROWS

    整行寫入,整行刪除,不可更新。

    2~3

    正常寫入時:寫主表,寫索引表。在刪除情境下需額外讀一次主表。效能僅次於IMMUTABLE。

    MUTABLE_LATEST

    可更新,可刪除。

    4

    讀主表,刪索引,寫索引,寫主表。

    MUTABLE_ALL

    無限制,可使用自訂時間戳記寫入。

    4

    讀主表,刪索引,寫索引,寫主表。

    說明
    • IMMUTABLE和IMMUTABLE_ROWS不涉及資料更新,無寫放大問題,成本最低。適合高吞吐寫的情境,如日誌、監控等。

    • IMMUTABLE不涉及刪除,所以可充分利用Lindorm的多IDC部署,實現多活的資料訪問。

    • 選擇兩類IMMUTABLE可以有效降低索引情境下的寫時延,提高整體吞吐。實際的業務中,如果不滿足IMMUTABLE情境,可以通過資料冗餘來改造成IMMUTABLE情境。

  • 更新自訂時間戳記的索引:Lindorm支援自訂時間戳記進行寫入,可以在任意時間戳記進行資料更新,由系統來判斷只有時間戳記最大的資料生效。自訂時間戳記特性在控制資料有效期間、亂序、等冪等情境中發揮著重要的作用,在HBase中有廣泛的應用。Lindorm支援列級時間戳記,主表支援自訂時間戳記寫入資料。但在支援二級索引和時間戳記的NoSQL系統中,支援自訂時間戳記索引更新的,就比較罕見了。因為時間戳記亂序寫入很難有效維護索引資料的更新和刪除。Lindorm全域二級索引解決了這個問題,支援列層級自訂時間戳記更新。下面是兩個使用自訂時間戳記的實際業務情境。

    • 匯入與即時並存:在需要同時即時更新和歷史資料匯入的情境下,即時更新可以使用目前時間,而歷史資料匯入可以使用昨天23:59:59這個時間。所以當天未更新過的資料可以通過匯入操作而更新,已更新過的資料也不會被匯入覆蓋。

    • 追訊息:業務系統通過訊息來觸發一系列處理邏輯,在訊息出現積壓時,系統可以跳過積壓的訊息,直接處理當前訊息,並在事後通過追訊息來處理之前積壓的任務。或者,當商務邏輯有問題時,系統也可以跳過一部分訊息來規避問題,在業務修複後重新處理。此時,業務可以通過使用訊息本身的時間來寫入資料,以此來保證追的訊息和正常訊息的準確覆蓋關係。

  • 全冗餘索引:為了避免查詢索引之後再回查主表,通常會在索引表中冗餘一部分主表列,也稱為冗餘索引或覆蓋索引。全冗餘索引是比較常用的冗餘方案。Lindorm支援三種冗餘模式,可以在主表Schema變化以及動態列情境下簡單的實現全冗餘索引。

    • 冗餘指定的列:顯式指定要冗餘主表的哪些列。

    • 冗餘主表Schema中的所有列:當您需要全冗餘索引時,不需要在CREATE INDEX中將主表的每一列都顯式添加進來,而是通過一個常量來描述冗餘所有列,當主表新增列時,全冗餘索引表會自動冗餘這個新增列,無需重建索引。也無需擔心新增列的查詢會導致回查主表了。

    • 冗餘動態列:Lindorm支援固定Schema和鬆散Schema(即動態列)。通過DYNAMIC冗餘模式,索引表能夠自動冗餘主表中的所有動態列,也會冗餘主表Schema中的所有列。

文法參考

二級索引的文法詳細說明,請參見以下文檔:

建立二級索引

建立完Lindorm主表後,可以為主表的相應列建立二級索引。以下是建立二級索引的樣本。

-- 建立主表
CREATE TABLE test (
  p1 VARCHAR NOT NULL,
  p2 INTEGER NOT NULL,
  c1 BIGINT,
  c2 DOUBLE,
  c3 VARCHAR,
  c5 GEOMETRY(POINT),
  PRIMARY KEY(p1, p2)
) WITH (CONSISTENCY = 'strong', MUTABILITY='MUTABLE_LATEST');

-- 對c3列建立二級索引,冗餘所有列
CREATE INDEX idx1 ON test(c3 desc) WITH (INDEX_COVERED_TYPE ='COVERED_ALL_COLUMNS_IN_SCHEMA');

-- 基於索引表進行查詢,因為對c3構建索引,當指定c3進行查詢會對應命中索引表
SELECT * FROM test WHERE c3 = 'data'; 
說明
  • 建立索引有同步建立和非同步建立兩種方式,在存量資料不大的情況下,可以使用同步建立。其他情況下可以使用非同步建立。具體的文法請參見CREATE INDEX

  • 在已有資料的表中添加新的索引時,CREATE INDEX命令會同時將主錶的歷史資料同步到索引表中,如果主表很大時,CREATE INDEX會非常耗時間(資料同步任務是在服務端執行的,即使刪除Lindorm Shell進程也不會影響資料同步任務)。

查看二級索引

通過Lindorm寬表SQL可以查看建立的二級索引狀態。以下是查看二級索引的樣本。

SHOW INDEX FROM test;
說明

通過樣本可以展示出test主表下建立的索引名和索引類型。

修改二級索引狀態

建立完二級索引後,如果主表有存量資料,需要手動對索引進行一次Rebuild操作,具體文法請參見BUILD INDEX;若主表沒有存量資料,則可以直接使用修改二級索引文法來修改二級索引表狀態。以下是修改二級索引狀態的樣本:

ALTER INDEX IF EXISTS idx1 ON test ACTIVE;
ALTER INDEX idx1 ON test DISABLED;
說明

當二級索引狀態為DISABLED時,直接修改為ACTIVE狀態會導致資料缺失,因此修改前需要進行一次Rebuild操作。

刪除二級索引

通過以下樣本刪除對應主表中的相關二級索引。

DROP INDEX IF EXISTS idx1 ON test;
說明

刪除索引操作需要您有Trash許可權。

查詢最佳化

Lindorm依據RBO(Rule Based Optimization)策略進行二級索引選擇。根據查詢條件匹配索引表的首碼,選擇匹配程度最高的索引表作為本次查詢使用的索引。通過以下樣本可以更好的理解。

-- 主表和索引表如下
CREATE TABLE dt (rowkey varchar, c1 varchar, c2 varchar, c3 varchar, c4 varchar, c5 varchar, PRIMARY KEY(rowkey));
CREATE INDEX idx1 ON dt (c1);
CREATE INDEX idx2 ON dt(c2,c3,c4);
CREATE INDEX idx3 ON dt(c3) INCLUDE(c1,c2,c4);
CREATE INDEX idx1 ON dt(c5 desc) WITH (INDEX_COVERED_TYPE ='COVERED_ALL_COLUMNS_IN_SCHEMA');

-- 查詢最佳化如下
SELECT rowkey FROM dt WHERE c1 = 'a';
SELECT rowkey FROM dt WHERE c2 = 'b' AND c4 = 'd';
SELECT * FROM dt WHERE c2 = 'b' AND c3 >= 'c' AND c3 < 'f';
SELECT * FROM dt WHERE c5 = 'c';
說明
  • SELECT rowkey FROM dt WHERE c1 = 'a';表示選擇索引表idx1

  • SELECT rowkey FROM dt WHERE c2 = 'b' AND c4 = 'd';表示選擇索引表idx2,從中尋找所有滿足c2=b條件的行,然後逐行按c4=d進行過濾。雖然c4是索引列之一,但因WHERE條件中缺少c3列,無法匹配idx2的首碼。

  • SELECT * FROM dt WHERE c2 = 'b' AND c3 >= 'c' AND c3 < 'f';表示選擇索引表idx2,由於是select *,而索引表裡並未包含主表的所有列,因此在查詢索引之後,還要回查一次主表。回查主表時,回查的Rowkey可能散布在主表的各個地方,因此,可能會消耗多次RPC。回查的資料量越大,RT越長。

  • SELECT * FROM dt WHERE c5 = 'c';表示選擇索引表idx4idx4是全冗餘索引,所以select *不需要回查主表。

使用限制

  • 不同主表可以有同名索引,如dt表有索引Idx1,foo表也有索引Idx1,但同一主表下不允許有同名索引。

  • 只能為Version為1的表建索引,不支援為多版本的表建索引。

  • 對有TTL的主表建索引,不能單獨為索引表設定TTL,索引表會自動繼承主表的TTL。

  • 索引列最多不超過3個。

  • 索引列和主表主鍵,總長度不能超過30 KB。不建議使用大於100位元組的列作為索引列。

  • 單個主表的索引表個數最多不超過5個,過多索引會造成儲存成本過高,以及寫入耗時過長。

  • 一次查詢最多能命中一個索引,不支援多索引聯集查詢(Index Merge Query)。

  • 建立索引時會將主表的資料同步到索引中,對資料多的表建索引會導致Create_Index命令耗時過長。

  • 二級索引不支援batch increase功能。

  • 命中二級索引的排序與主表不一樣。

  • 僅支援為通過SQL或API寫入的資料構建二級索引,不支援為Bulkload(大量匯入)至Lindorm的資料構建二級索引。

問題答疑(大量匯入)至

對於索引使用上的任何問題,您可以通過DingTalk聯絡雲Lindorm答疑或工單諮詢,具體操作,請參見支援人員