全部產品
Search
文件中心

Tablestore:建立多元索引

更新時間:Sep 14, 2024

通過控制台、命令列或SDK您可以為某一個表建立一個或多個多元索引,然後使用多元索引對錶中的資料進行查詢和簡單分析。

最佳使用方式

請根據實際查詢需求確定在一張資料表中建立多元索引的個數。

例如有一張資料表有5個欄位,分別為id、name、age、city、sex,需要按照name、age或city查詢資料時,有兩種建立多元索引的方式。

  • 方法一:一個欄位建立一個多元索引

    按照name、age或city欄位分別建立多元索引,名稱分別為name_index、age_index、city_index。

    • 如果按照城市查詢學生,則查詢city_index,如果按照年齡查詢學生,則查詢age_index。

    • 如果查詢年齡小於12歲且城市是成都的學生,此種方式就無法查詢。

    此方式的實作類別似於全域二級索引,使用此方式建立多元索引會帶來更高的費用,因此不建議使用此方式建立多元索引。

  • 方法二:多個欄位建立在一個多元索引中

    將name、age和city欄位建立在一個多元索引中,名稱為student_index。

    • 如果按照城市查詢學生,則查詢student_index中city欄位;如果按照年齡查詢學生,則查詢student_index中age欄位。

    • 如果查詢年齡小於12歲且城市是成都的學生,則查詢student_index中age和city欄位。

    此方式才能發揮多元索引最大優勢,不僅功能更豐富,而且價格會更低。極力推薦使用此方式建立多元索引。

使用限制

  • 建立索引的時效性

    建立多元索引後,需要等幾秒鐘才能使用,但是此過程中不影響資料寫入,隻影響索引元資訊的查詢和索引查詢。

  • 建立多元索引時,請確保多元索引中的欄位類型與表中的欄位類型相匹配。更多資訊,請參見基礎資料類型及映射

  • 數量限制

    更多資訊,請參見多元索引限制

參數

建立多元索引時,需要指定資料表名稱(tableName)、多元索引名稱(indexName)和索引的結構資訊(indexSchema),其中indexSchema包含fieldSchemas(Index的所有欄位的設定)、indexSetting(索引設定)和indexSort(索引預排序設定)。詳細參數說明請參見下表。

參數

說明

tableName

資料表名稱。

indexName

多元索引名稱。

fieldSchemas

fieldSchema的列表,每個fieldSchema包含如下內容:

  • fieldName(必選):建立多元索引的欄位名,即列名,類型為String。

    多元索引中的欄位可以是主鍵列或者屬性列。

  • fieldType(必選):欄位類型,類型為FieldType.XXX。更多資訊,請參見基礎資料類型及映射

  • array(可選):是否為數組,類型為Boolean。

    如果設定為true,則表示該列是一個數組,在寫入時,必須按照JSON數組格式寫入,例如["a","b","c"]。

    由於Nested類型是一個數組,當fieldType為Nested類型時,無需設定此參數。

  • analyzer(可選):分詞器類型。當欄位類型為Text時,可以設定此參數;如果不設定此參數,則預設分詞器類型為單字分詞。關於分詞的更多資訊,請參見分詞

  • isVirtualField(可選):該欄位是否為虛擬列,類型為Boolean。預設值為false,表示欄位不是虛擬列。如果要使用虛擬列,請設定此參數為true。關於虛擬列的更多資訊,請參見虛擬列

  • sourceFieldName(可選):資料表中的欄位名稱,類型為String。當設定isVirtualField為true時,必須設定此參數。

  • dateFormats(可選):日期的格式,類型為String。當欄位類型為Date時,必須設定此參數。更多資訊,請參見日期時間類型

  • enableHighlighting(可選):是否開啟查詢高亮功能,類型為Boolean。預設值為false,表示不開啟查詢高亮。如果要使用查詢高亮,請設定此參數為true。僅Text類型欄位支援查詢高亮功能。關於查詢高亮的更多資訊,請參見查詢高亮

    重要

    目前此參數只支援通過Table StoreSDK進行配置。

  • vectorOptions(可選):向量欄位類型的屬性參數。當欄位類型為Vector時,必須設定此參數。包括如下內容:

    • dataType:向量資料類型。當前僅支援float32。如果有其他類型需求,請提交工單聯絡我們。

    • dimension:向量維度。關於維度限制說明請參見多元索引限制

    • metricType:向量之間距離度量的演算法,支援歐氏距離(euclidean)、餘弦相似性(cosine)、點積(dot_product)。

      • 歐氏距離(euclidean):多維空間中兩個向量之間的直線距離。出於效能考慮,Table Store中的歐氏距離演算法未進行最後的平方根計算。歐氏距離的評分越大表示兩個向量的相似性越大。

      • 餘弦相似性(cosine):向量空間中兩個向量間夾角的餘弦值。餘弦相似性的評分越高表示兩個向量的相似性越大。常用於文本資料的相似性計算。

      • 點積(dot_product):維度相同的兩個向量的對應座標相乘,然後將結果相加。點積的評分越高標識兩個向量的相似性越大。

      關於如何選用距離度量演算法的更多資訊,請參見附錄:距離度量演算法說明

indexSetting

索引設定,包含routingFields設定。

routingFields(可選):自訂路由欄位。可以選擇部分主鍵列作為路由欄位,在進行索引資料寫入時,會根據路由欄位的值計算索引資料的分布位置,路由欄位的值相同的記錄會被索引到相同的資料分區中。

indexSort

索引預排序設定,包含sorters設定。如果不設定,則預設按照主鍵排序。

重要

含有Nested類型的索引不支援indexSort,沒有預排序。

sorters(可選):索引的預排序方式,支援按照主鍵排序和欄位值排序。更多資訊,請參見排序和翻頁

timeToLive

選擇性參數,預設值為-1。資料生命週期(TTL),即資料的儲存時間。

當資料的儲存時間超過設定的資料生命週期時,系統會自動清理超過資料生命週期的資料。

資料生命週期至少為86400秒(一天)或-1(資料永不到期)。

多元索引生命週期的使用方式,請參見生命週期管理

注意事項

  • 當要實現全文檢索索引時,您可以在多元索引中將欄位設定為可分詞字串(TEXT)類型並為TEXT類型的欄位設定分詞,然後使用匹配查詢短語匹配查詢功能查詢資料。關於分詞的更多資訊,請參見分詞

  • 在不修改Table Store的儲存結構及資料的情況下,當要實現新欄位和新資料類型的查詢功能時,您可以在多元索引中將欄位設定為虛擬列。更多資訊,請參見虛擬列

  • 當要使用日期資料類型進行資料查詢時,您可以在多元索引中將資料表中的整型(Integer)或字串(String)類型的資料對應為日期資料類型。更多資訊,請參見日期時間類型

  • 當要使用數值向量進行近似最近鄰查詢時,您可以在多元索引中將欄位設定為向量類型,然後使用向量檢索介紹與使用功能查詢資料。

  • 當要使用數群組類型儲存資料時,您可以在資料表中以String類型欄位儲存資料,然後在多元索引中將欄位設定為數組。

    在寫入資料到資料表中時,數群組類型欄位的值必須按照JSON數組格式寫入,例如["a","b","c"]。

    說明

    數群組類型僅是多元索引中的概念,資料表中還不支援數組。更多資訊,請參見數組和巢狀型別

  • 當要使用單欄位儲存存在層次關係或者一對多關聯性的資料時,您可以在多元索引中將欄位設定為巢狀型別,然後使用巢狀型別查詢功能查詢資料。

    在寫入資料到資料表中時,巢狀型別欄位的值必須按照JSON數組格式寫入,例如[{"tagName":"tag1", "score":0.8}, {"tagName":"tag2", "score":0.2}]

  • 當要儲存的資料為地理位置資訊時,您可以在多元索引中將欄位設定為地理位置(Geo-point)類型,然後使用地理距離查詢地理長方形範圍查詢地理多邊形範圍查詢功能查詢資料。

  • 系統預設使用分區鍵作為路由鍵,當要使用其他主鍵列作為路由鍵來定向搜尋指定資料分區,以減少長尾對延遲的影響時,您可以修改路由欄位配置。更多資訊,請參見多元索引路由欄位的使用

  • 多元索引預設按照主鍵升序的排序方式返回查詢結果,當要按照指定欄位值或主鍵降序進行預排序時,您可以修改預排序方式。更多資訊,請參見索引預排序

  • 當要實現自動清理多元索引中的歷史資料時,您可以使用多元索引的資料生命週期(TTL)功能有效地管理資料,減少資料存放區空間,降低儲存成本。更多資訊,請參見生命週期管理

  • 當要在查詢結果中高亮反白匹配到的關鍵詞時,您可以使用查詢高亮功能實現。更多資訊,請參見查詢高亮

使用方式

您可以使用控制台、命令列工具或者SDK進行建立多元索引操作。

進行多元索引建立之前,您需要完成如下準備工作。

  • 使用阿里雲帳號或者具有Table Store操作許可權的RAM使用者進行操作。如果需要為RAM使用者授權Table Store操作許可權,請參見通過RAM Policy為RAM使用者授權進行配置。

    使用SDK方式和命令列工具方式進行操作時,如果當前無可用AccessKey,則需要為阿里雲帳號或者RAM使用者建立AccessKey。具體操作,請參見建立AccessKey

  • 已建立資料表。具體操作,請參見資料表操作

  • 使用SDK方式進行操作時,還需要完成初始化Client。具體操作,請參見初始化OTSClient

  • 使用命令列工具進行操作前,還需要完成下載並啟動命令列工具,然後配置接入執行個體資訊。具體操作,請參見下載命令列工具啟動並配置接入資訊

使用控制台

通過控制台建立一個多元索引。

  1. 進入索引管理頁簽。

    1. 登入Table Store控制台

    2. 在頁面上方,選擇資源群組和地區。

    3. 概覽頁面,單擊執行個體名稱或在操作列單擊執行個體管理

    4. 執行個體詳情頁簽的資料表列表地區,單擊資料表名稱或在操作列單擊索引管理

  2. 索引管理頁簽,單擊建立多元索引

  3. 建立索引對話方塊,建立多元索引。

    image.png

    1. 系統預設會自動產生索引名,可根據需要設定索引名。

    2. 選擇Schema產生方式。

      重要

      欄位名欄位類型需與資料表匹配。資料表欄位類型與多元索引欄位類型的對應關係請參見基礎資料類型及映射

      • 當設定Schema產生方式手動錄入時,手動輸入欄位名,選擇欄位類型以及設定是否開啟數組。

      • 當設定Schema產生方式自動產生時,系統會自動將資料表的主鍵列和屬性列作為索引欄位,可根據需要選擇欄位類型以及設定是否開啟數組。

      說明

      在部分情況下如果要最佳化效能,則可以使用虛擬列。關於虛擬列的更多資訊,請參見虛擬列

    3. 如果需要配置資料生命週期、路由鍵、索引預排序等選項,請開啟進階選項開關,並根據下表說明配置參數。

      參數

      說明

      路由鍵

      自訂路由欄位。可以選擇部分主鍵列作為路由欄位,在進行索引資料寫入時,Table Store會根據路由欄位的值計算索引資料的分布位置,路由欄位的值相同的記錄會被索引到相同的資料分區中。

      資料生命週期

      多元索引中資料的儲存時間。預設值為-1,表示資料永不到期。資料生命週期至少為86400秒(一天)或-1(資料永不到期)。

      如果需要系統自動清理多元索引中的歷史資料,您可以配置資料生命週期為指定時間。當資料的儲存時間超過設定的資料生命週期時,系統會自動清理超過資料生命週期的資料。

      預排序

      多元索引預設按照設定的索引預排序方式進行排序,用於確定資料的預設返回順序。

      索引預排序只支援按照主鍵排序和按照欄位值排序兩種方式。如果未自訂預排序,則預設為主鍵排序,您可以根據實際查詢情境指定預排序方式。

      重要

      含有Nested類型欄位的多元索引不支援索引預排序。

  4. 單擊確定

    多元索引建立完成後,在索引列表的操作列,單擊索引詳情,可查看索引表的索引基本資料、索引計量、路由鍵、索引欄位和預排序等資訊。

使用命令列工具

通過命令列工具執行create_search_index命令建立多元索引。更多資訊,請參見多元索引

  1. 執行create_search_index命令建立一個多元索引search_index。

    create_search_index -n search_index
  2. 根據系統提示輸入索引Schema,樣本如下:

    索引Schema包括IndexSetting(索引設定)、FieldSchemas(Index的所有欄位的設定)和IndexSort(索引預排序設定)。關於索引Schema的更多資訊,請參見建立多元索引

     {
    
        "IndexSetting": {
            "RoutingFields": null
        },
        "FieldSchemas": [
            {
                "FieldName": "gid",
                "FieldType": "LONG",
                "Index": true,
                "EnableSortAndAgg": true,
                "Store": true,
                "IsArray": false,
                "IsVirtualField": false
            },
            {
                "FieldName": "uid",
                "FieldType": "LONG",
                "Index": true,
                "EnableSortAndAgg": true,
                "Store": true,
                "IsArray": false,
                "IsVirtualField": false
            },
            {
                "FieldName": "col2",
                "FieldType": "LONG",
                "Index": true,
                "EnableSortAndAgg": true,
                "Store": true,
                "IsArray": false,
                "IsVirtualField": false
            },
            {
                "FieldName": "col3",
                "FieldType": "TEXT",
                "Index": true,
                "Analyzer": "single_word",
                "AnalyzerParameter": {
                    "CaseSensitive": true,
                    "DelimitWord": null
                },
                "EnableSortAndAgg": false,
                "Store": true,
                "IsArray": false,
                "IsVirtualField": false
            },
            {
                "FieldName": "col1",
                "FieldType": "KEYWORD",
                "Index": true,
                "EnableSortAndAgg": true,
                "Store": true,
                "IsArray": false,
                "IsVirtualField": false
            },
            {
                "FieldName": "col3V",
                "FieldType": "LONG",
                "Index": true,
                "EnableSortAndAgg": true,
                "Store": true,
                "IsArray": false,
                "IsVirtualField": true,
                "SourceFieldNames": [
                    "col3"
                ]
            }
        ]
    }

使用SDK

您可以通過Java SDKGo SDKPython SDKNode.js SDK.NET SDKPHP SDK建立多元索引。此處以Java SDK為例介紹建立多元索引的操作。

建立多元索引時使用預設配置

以下樣本用於建立一個多元索引。該多元索引包含Col_Keyword(KEYWORD類型)、Col_Long(LONG類型)和Col_Vector(VECTOR類型)三列,按照資料表主鍵進行預排序且資料永不到期。

private static void createSearchIndex(SyncClient client) {
    CreateSearchIndexRequest request = new CreateSearchIndexRequest();
    //設定資料表名稱。
    request.setTableName("<TABLE_NAME>"); 
    //設定多元索引名稱。
    request.setIndexName("<SEARCH_INDEX_NAME>"); 
    IndexSchema indexSchema = new IndexSchema();
    indexSchema.setFieldSchemas(Arrays.asList(
            //設定欄位名和類型。
            new FieldSchema("Col_Keyword", FieldType.KEYWORD), 
            new FieldSchema("Col_Long", FieldType.LONG)));
            // 設定向量類型。
            new FieldSchema("Col_Vector", FieldType.VECTOR).setIndex(true)
                    // 向量維度為4,相似性演算法為點積。
                    .setVectorOptions(new VectorOptions(VectorDataType.FLOAT_32, 4, VectorMetricType.DOT_PRODUCT))
    ));
    request.setIndexSchema(indexSchema);
    //調用client建立多元索引。
    client.createSearchIndex(request); 
}

建立多元索引時指定IndexSort

以下樣本用於建立一個多元索引,多元索引包含Col_Keyword(KEYWORD類型)、Col_Long(LONG類型)、Col_Text(TEXT類型)和Timestamp(LONG類型)四列,同時配置按照Timestamp列進行預排序。

private static void createSearchIndexWithIndexSort(SyncClient client) {
    CreateSearchIndexRequest request = new CreateSearchIndexRequest();
    //設定資料表名稱。
    request.setTableName("<TABLE_NAME>"); 
    //設定多元索引名稱。
    request.setIndexName("<SEARCH_INDEX_NAME>"); 
    IndexSchema indexSchema = new IndexSchema();
    indexSchema.setFieldSchemas(Arrays.asList(
            new FieldSchema("Col_Keyword", FieldType.KEYWORD),
            new FieldSchema("Col_Long", FieldType.LONG),
            new FieldSchema("Col_Text", FieldType.TEXT),
            new FieldSchema("Timestamp", FieldType.LONG)
                    .setEnableSortAndAgg(true)));
    //設定按照Timestamp列進行預排序。
    indexSchema.setIndexSort(new Sort(
            Arrays.<Sort.Sorter>asList(new FieldSort("Timestamp", SortOrder.ASC))));
    request.setIndexSchema(indexSchema);
    //調用client建立多元索引。
    client.createSearchIndex(request);
}

建立多元索引時設定生命週期

重要

請確保資料表的更新狀態為禁止。

以下樣本用於建立一個多元索引,多元索引包含Col_Keyword(KEYWORD類型)和Col_Long(LONG類型)兩列,同時指定多元索引生命週期為7天。

// 請使用5.12.0及以上版本的Java SDK。
public static void createIndexWithTTL(SyncClient client) {
    int days = 7;
    CreateSearchIndexRequest createRequest = new CreateSearchIndexRequest();
    //設定資料表名稱。
    createRequest.setTableName("<TABLE_NAME>");
    //設定多元索引名稱。
    createRequest.setIndexName("<SEARCH_INDEX_NAME>");
    IndexSchema indexSchema = new IndexSchema();
    indexSchema.setFieldSchemas(Arrays.asList(
            //設定欄位名和類型。
            new FieldSchema("Col_Keyword", FieldType.KEYWORD), 
            new FieldSchema("Col_Long", FieldType.LONG)));
    createRequest.setIndexSchema(indexSchema);
    //設定多元索引TTL。
    createRequest.setTimeToLiveInDays(days);
    //調用client建立多元索引。
    client.createSearchIndex(createRequest);
}

建立多元索引時指定虛擬列

以下樣本用於建立一個多元索引,多元索引包含Col_Keyword(KEYWORD類型)和Col_Long(LONG類型)兩列,同時建立虛擬列Col_Keyword_Virtual_Long(LONG類型)和Col_Long_Virtual_Keyword(KEYWORD類型)。Col_Keyword_Virtual_Long映射為資料表中Col_Keyword列,虛擬列Col_Long_Virtual_Keyword映射為資料表中Col_Long列。

private static void createSearchIndex(SyncClient client) {
    CreateSearchIndexRequest request = new CreateSearchIndexRequest();
    //設定資料表名稱。
    request.setTableName("<TABLE_NAME>"); 
    //設定多元索引名稱。
    request.setIndexName("<SEARCH_INDEX_NAME>"); 
    IndexSchema indexSchema = new IndexSchema();
    indexSchema.setFieldSchemas(Arrays.asList(
        //設定欄位名和類型。
        new FieldSchema("Col_Keyword", FieldType.KEYWORD), 
        //設定欄位名和類型。
        new FieldSchema("Col_Keyword_Virtual_Long", FieldType.LONG) 
             //設定欄位是否為虛擬列。
            .setVirtualField(true) 
             //虛擬列對應的資料表中欄位。
            .setSourceFieldName("Col_Keyword"), 
        new FieldSchema("Col_Long", FieldType.LONG),
        new FieldSchema("Col_Long_Virtual_Keyword", FieldType.KEYWORD)
            .setVirtualField(true)
            .setSourceFieldName("Col_Long")));
    request.setIndexSchema(indexSchema);
    //調用client建立多元索引。
    client.createSearchIndex(request); 
}

建立多元索引時開啟查詢高亮

以下樣本用於建立一個多元索引,多元索引包含Col_Keyword(KEYWORD類型)、Col_Long(LONG類型)和Col_Text(TEXT類型)三列,同時為Col_Text列開啟查詢高亮功能。

private static void createSearchIndexwithHighlighting(SyncClient client) {
    CreateSearchIndexRequest request = new CreateSearchIndexRequest();
    //設定資料表名稱。
    request.setTableName("<TABLE_NAME>"); 
    //設定多元索引名稱。
    request.setIndexName("<SEARCH_INDEX_NAME>"); 
    IndexSchema indexSchema = new IndexSchema();
    indexSchema.setFieldSchemas(Arrays.asList(
            //設定欄位名和類型。
            new FieldSchema("Col_Keyword", FieldType.KEYWORD), 
            new FieldSchema("Col_Long", FieldType.LONG),
            //為欄位開啟查詢高亮功能。
            new FieldSchema("Col_Text", FieldType.TEXT).setIndex(true).setEnableHighlighting(true)
    ));
    request.setIndexSchema(indexSchema);
    //調用client建立多元索引。
    client.createSearchIndex(request); 
}

後續操作

建立多元索引後,您可以通過多元索引進行資料查詢、資料分析與資料匯出。

操作

可選功能

資料查詢

請根據實際業務情境選擇合適的查詢方式。

當通過Search介面查詢資料時,如果要對結果集進行排序或者翻頁,您可以使用排序和翻頁功能來實現。具體操作,請參見排序和翻頁

資料分析

統計彙總

資料匯出

並發匯出資料

相關文檔

建立多元索引後,請根據需要執行相應操作。

  • 如果希望清理多元索引中的歷史資料或者希望延長資料儲存時間,您可以修改多元索引的資料生命週期。具體操作,請參見生命週期管理

  • 如果要在多元索引中新增、更新或者刪除索引列,您可以使用動態修改schema功能實現。具體操作,請參見動態修改schema

  • 如果要擷取某個資料表關聯的所有多元索引的列表資訊,您可以使用列出多元索引列表功能實現。具體操作,請參見列出多元索引列表

  • 如果要查詢多元索引的描述資訊,包括多元索引的欄位資訊和索引配置等,您可以使用查詢多元索引描述資訊功能實現。具體操作,請參見查詢多元索引描述資訊

  • 如果不再需要使用多元索引,您可以刪除多元索引。具體操作,請參見刪除多元索引

  • 您還可以使用SQL查詢功能或者通過MaxCompute、Spark、Hive或者HadoopMR、Function Compute、Flink、PrestoDB等計算引擎計算與分析表中資料。具體操作,請參見SQL查詢計算與分析概述

附錄:距離度量演算法說明

向量的距離度量演算法說明請參見下表,其中評分公式的值越大表示的相似性越大。

MetricType

評分公式

效能

說明

歐氏距離

(euclidean)

image

較高

多維空間中兩個向量之間的直線距離。出於效能考慮,Table Store中的歐氏距離演算法未進行最後的平方根計算。歐氏距離的評分越大表示兩個向量的相似性越大。

點積

(dot_product)

image

最高

維度相同的兩個向量的對應座標相乘,然後將結果相加。點積的評分越高表示兩個向量的相似性越大。

Float32向量必須在寫入表前進行歸一化(例如使用L2範數進行歸一化),否則會出現查詢效果差、構建向量索引慢、查詢效能差等潛在問題。

餘弦相似性

(cosine)

image

較低

向量空間中兩個向量間夾角的餘弦值。餘弦相似性的評分越高表示兩個向量的相似性越大。常用於文本資料的相似性計算。

由於0無法作為除數,無法完成餘弦相似性的計算,因此Float32向量的平方和不允許為0

餘弦相似性計算複雜,推薦您在寫入資料到表之前進行向量的歸一化,然後使用點積(dot_product)作為向量距離的度量演算法。

向量歸一化的範例程式碼如下:

  public static float[] l2normalize(float[] v, boolean throwOnZero) {
    double squareSum = 0.0f;
    int dim = v.length;
    for (float x : v) {
      squareSum += x * x;
    }
    if (squareSum == 0) {
      if (throwOnZero) {
        throw new IllegalArgumentException("can't normalize a zero-length vector");
      } else {
        return v;
      }
    }
    double length = Math.sqrt(squareSum);
    for (int i = 0; i < dim; i++) {
      v[i] /= length;
    }
    return v;
  }