建立多元索引時,您可以選擇部分主鍵列作為路由欄位,在進行索引資料寫入時,Table Store會根據路由欄位的值計算索引資料的分布位置,路由欄位的值相同的記錄會被索引到相同的資料分區中。
使用流程
建立索引時,指定一個或多個路由欄位。
您在建立多元索引時指定了路由欄位後,索引資料的讀寫都會使用該路由欄位進行定位。
多元索引的路由鍵支援動態改變。如果想使用系統預設路由(即主鍵列路由)或者重新指定其他欄位為路由欄位,您可以通過動態修改schema功能實現路由鍵修改。更多資訊,請參見動態修改schema。
重要路由欄位只能是Table Store的主鍵列。
在索引查詢時,在查詢請求中指定路由欄位值。
查詢資料時使用路由定向搜尋指定資料分區,可以減少長尾對延遲的影響。對於自訂路由的查詢請求,都要求使用者提供路由欄位。如不指定路由鍵,雖然查詢結果一樣,但查詢時會訪問無關的資料分區,浪費系統資源,增加訪問延遲。
重要路由鍵可配置為單值或多值,不支援範圍。
使用方式
您可以使用控制台、命令列工具或者SDK進行路由鍵配置。路由鍵支援在建立多元索引時配置或者在建立多元索引後修改。此處以建立多元索引時配置路由鍵為例介紹。
在建立多元索引後,如需修改多元索引的路由鍵,請通過動態修改schema實現。具體操作,請參見動態修改schema。
已建立資料表,且資料表的最大版本數(max Versions)必須為1,資料生命週期(Time to Live)必須滿足如下條件中的任意一個。具體操作,請參見資料表操作。
資料表的資料生命週期為-1(資料永不到期)。
資料表的資料生命週期不為-1時,資料表為禁止更新狀態(即是否允許更新為否)。
使用SDK方式進行操作時,還需要完成初始化Client。具體操作,請參見初始化OTSClient。
使用命令列工具方式進行操作前,還需要完成下載並啟動命令列工具,然後配置接入執行個體資訊。具體操作,請參見下載命令列工具和啟動並配置接入執行個體。
使用控制台
在Table Store控制台建立多元索引時,開啟進階選項開關並進行路由鍵配置,如下圖所示。具體操作,請參見建立多元索引。
使用命令列工具
通過命令列工具執行create_search_index
命令建立多元索引。更多資訊,請參見多元索引。
建立多元索引時指定路由鍵。
以下樣本用於建立名稱為mysearchindex的多元索引,該多元索引有gid(long類型)、uid(long類型)、col2(long類型)、col3(text類型)、col1(keyword類型)何col3V(long類型)欄位。其中col3V為虛擬列,對應原始列為col3。多元索引的路由鍵配置為uid。
create_search_index -n mysearchindex
根據系統提示輸入索引schema,請根據實際欄位修改樣本後再使用。樣本如下:
{ "IndexSetting": { "RoutingFields": ["uid"] }, "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" ] }] }
使用多元索引查詢資料時指定路由鍵。
以下樣本用於使用mysearchindex查詢col2列小於200的行資料。查詢時帶有多元索引路由鍵uid。
search -n search_index --return_all_indexed
根據系統提示輸入查詢條件,請根據實際欄位修改樣本後再使用。樣本如下:
說明此處以RangeQuery(範圍查詢)為例介紹,如需使用其他查詢方式,請參見多元索引基礎功能。
{ "Offset": -1, "Limit": 10, "Collapse": null, "Sort": null, "GetTotalCount": true, "Token": null, "IndexSetting": { "RoutingFields": ["uid"] }, "Query": { "Name": "RangeQuery", "Query": { "FieldName": "col2", "From": null, "To": 200, "IncludeLower": false, "IncludeUpper": false } } }
使用SDK
您可以使用Java SDK、Go SDK、Python SDK、Node.js SDK、.NET SDK和PHP SDK在建立多元索引時配置路由鍵。此處以Java SDK為例介紹路由鍵的配置和使用。
以下樣本用於建立order資料表時建立order_index多元索引並指定路由欄位為user_id欄位。然後寫入資料並帶上路由欄位進行查詢。該資料表有order_id(string類型)和user_id(string類型);該多元索引有product_name(keyword類型)、order_time(long類型)和user_id(keyword類型)欄位,多元索引的路由鍵為user_id欄位。
private static void testRoute(SyncClient client) throws InterruptedException {
//建立表。
TableMeta meta = new TableMeta("order");
meta.addPrimaryKeyColumn("order_id",PrimaryKeyType.STRING);
meta.addPrimaryKeyColumn("user_id",PrimaryKeyType.STRING);
TableOptions options = new TableOptions();
options.setMaxVersions(1);
options.setTimeToLive(-1);
CreateTableRequest request = new CreateTableRequest(meta,options);
request.setReservedThroughput(new ReservedThroughput(new CapacityUnit(0, 0)));
CreateTableResponse response = client.createTable(request);
//建立多元索引並指定路由欄位。
CreateSearchIndexRequest searchIndexRequest = new CreateSearchIndexRequest();
//訂單表。
searchIndexRequest.setTableName("order");
//訂單表索引名。
searchIndexRequest.setIndexName("order_index");
IndexSchema indexSchema = new IndexSchema();
IndexSetting indexSetting = new IndexSetting();
//設定user_id為路由欄位。
indexSetting.setRoutingFields(Arrays.asList("user_id"));
indexSchema.setIndexSetting(indexSetting);
//添加索引欄位。此處只是給出樣本,您可以根據業務需求添加索引欄位。
indexSchema.setFieldSchemas(Arrays.asList(
new FieldSchema("product_name",FieldType.KEYWORD).setStore(true).setIndex(true),
new FieldSchema("order_time",FieldType.LONG).setStore(true).setEnableSortAndAgg(true).setIndex(true),
new FieldSchema("user_id",FieldType.KEYWORD).setStore(true).setIndex(true)
));
searchIndexRequest.setIndexSchema(indexSchema);
client.createSearchIndex(searchIndexRequest);
//等待資料表載入。
Thread.sleep(6*1000);
//插入一些測試資料。
String[] productName = new String[]{"product a", "product b", "product c"};
String[] userId = new String[]{"00001", "00002", "00003", "00004", "00005"};
for (int i = 0; i < 100; i++){
PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
primaryKeyBuilder.addPrimaryKeyColumn("order_id",PrimaryKeyValue.fromString(i+""));
primaryKeyBuilder.addPrimaryKeyColumn("user_id",PrimaryKeyValue.fromString(userId[i%(userId.length)]));
PrimaryKey primaryKey = primaryKeyBuilder.build();
RowPutChange rowPutChange = new RowPutChange("order",primaryKey);
//寫入屬性列。
rowPutChange.addColumn("product_name",ColumnValue.fromString(productName[i%(productName.length)]));
rowPutChange.addColumn("order_time",ColumnValue.fromLong(System.currentTimeMillis()));
rowPutChange.setCondition(new Condition(RowExistenceExpectation.IGNORE));
client.putRow(new PutRowRequest(rowPutChange));
}
//等待資料同步到多元索引。
Thread.sleep(20*1000);
//帶上路由欄位的查詢。
SearchRequest searchRequest = new SearchRequest();
searchRequest.setTableName("order");
searchRequest.setIndexName("order_index");
MatchQuery matchQuery = new MatchQuery();
matchQuery.setFieldName("user_id");
matchQuery.setText("00002");
SearchQuery searchQuery = new SearchQuery();
searchQuery.setQuery(matchQuery);
searchQuery.setGetTotalCount(true);
SearchRequest.ColumnsToGet columnsToGet = new SearchRequest.ColumnsToGet();
columnsToGet.setReturnAll(true);
searchRequest.setColumnsToGet(columnsToGet);
searchRequest.setSearchQuery(searchQuery);
PrimaryKeyBuilder pkbuild = PrimaryKeyBuilder.createPrimaryKeyBuilder();
pkbuild.addPrimaryKeyColumn("user_id",PrimaryKeyValue.fromString("00002"));
PrimaryKey routingValue = pkbuild.build();
searchRequest.setRoutingValues(Arrays.asList(routingValue));
SearchResponse searchResponse = client.search(searchRequest);
System.out.println(searchResponse.isAllSuccess());
System.out.println("totalCount:"+ searchResponse.getTotalCount());
System.out.println("RowCount:"+searchResponse.getRows().size());
}