Tablestore提供了GetRow介面用於讀取單行資料以及BatchGetRow、GetRange等介面用於讀取多行資料。
前提條件
- 已初始化OTSClient。具體操作,請參見初始化。
- 已建立資料表並寫入資料。
讀取單行資料
調用GetRow介面讀取一行資料。
- 如果該行存在,則返回該行的各主鍵列以及屬性列。
- 如果該行不存在,則返回中不包含行,並且不會報錯。
參數
參數 | 說明 |
---|---|
tableName | 資料表名稱。 |
primaryKey | 行的主鍵。 说明 設定的主鍵個數和類型必須和資料表的主鍵個數和類型一致。 |
columnsToGet | 讀取的列集合,列名可以是主鍵列或屬性列。 如果不設定返回的列名,則返回整行資料。 说明
|
maxVersions | 最多讀取的版本數。 说明 maxVersions與timeRange必須至少設定一個。
|
timeRange | 讀取版本號碼範圍或特定版本號碼的資料。更多資訊,請參見TimeRange。 说明 maxVersions與timeRange必須至少設定一個。
timestamp和 時間戳記的單位為毫秒,最小值為0,最大值為Long.MAX_VALUE。 |
filter | 使用過濾器,在服務端對讀取結果再進行一次過濾,只返回符合過濾器中條件的資料行。更多資訊,請參見過濾器。 说明 當columnsToGet和filter同時使用時,執行順序是先擷取columnsToGet指定的列,再在返回的列中進行條件過濾。 |
樣本
- 樣本1
讀取一行,設定讀取最新版本的資料和讀取的列。
private static void getRow(SyncClient client, String pkValue) { //構造主鍵。 PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder(); primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString(pkValue)); PrimaryKey primaryKey = primaryKeyBuilder.build(); //讀取一行資料,設定資料表名稱。 SingleRowQueryCriteria criteria = new SingleRowQueryCriteria(TABLE_NAME, primaryKey); //設定讀取最新版本。 criteria.setMaxVersions(1); GetRowResponse getRowResponse = client.getRow(new GetRowRequest(criteria)); Row row = getRowResponse.getRow(); System.out.println("讀取完畢,結果為: "); System.out.println(row); //設定讀取某些列。 criteria.addColumnsToGet("Col0"); getRowResponse = client.getRow(new GetRowRequest(criteria)); row = getRowResponse.getRow(); System.out.println("讀取完畢,結果為:"); System.out.println(row); }
- 樣本2
在讀取一行資料時使用過濾器。
private static void getRow(SyncClient client, String pkValue) { //構造主鍵。 PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder(); primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString(pkValue)); PrimaryKey primaryKey = primaryKeyBuilder.build(); //讀取一行資料,設定資料表名稱。 SingleRowQueryCriteria criteria = new SingleRowQueryCriteria(TABLE_NAME, primaryKey); //設定讀取最新版本。 criteria.setMaxVersions(1); //設定過濾器,當Col0列的值為0時,返回該行。 SingleColumnValueFilter singleColumnValueFilter = new SingleColumnValueFilter("Col0", SingleColumnValueFilter.CompareOperator.EQUAL, ColumnValue.fromLong(0)); //如果Col0列不存在,則不返回該行。 singleColumnValueFilter.setPassIfMissing(false); criteria.setFilter(singleColumnValueFilter); GetRowResponse getRowResponse = client.getRow(new GetRowRequest(criteria)); Row row = getRowResponse.getRow(); System.out.println("讀取完畢,結果為: "); System.out.println(row); }
- 樣本3
讀取一行中Col1列的資料,並對該列的資料執行正則過濾。
private static void getRow(SyncClient client, String pkValue) { SingleRowQueryCriteria criteria = new SingleRowQueryCriteria(tableName); //構造主鍵。 PrimaryKey primaryKey = PrimaryKeyBuilder.createPrimaryKeyBuilder() .addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString(pkValue)) .build(); criteria.setPrimaryKey(primaryKey); // 設定讀取最新版本。 criteria.setMaxVersions(1); // 設定過濾器,當cast<int>(regex(Col1)) > 100時,返回該行。 RegexRule regexRule = new RegexRule("t1:([0-9]+),", VariantType.Type.VT_INTEGER); SingleColumnValueRegexFilter filter = new SingleColumnValueRegexFilter("Col1", regexRule,SingleColumnValueFilter.CompareOperator.GREATER_THAN, ColumnValue.fromLong(100)); criteria.setFilter(filter); GetRowResponse getRowResponse = client.getRow(new GetRowRequest(criteria)); Row row = getRowResponse.getRow(); System.out.println("讀取完畢,結果為: "); System.out.println(row); }
批量讀取資料
調用BatchGetRow介面一次請求讀取多行資料,也支援一次對多張表進行讀取。BatchGetRow由多個GetRow子操作組成。構造子操作的過程與使用GetRow介面時相同,也支援使用過濾器。
批量讀取的所有行採用相同的參數條件,例如ColumnsToGet=[colA]
,則要讀取的所有行都唯讀取colA列。
BatchGetRow的各個子操作獨立執行,Tablestore會分別返回各個子操作的執行結果。
由於批量讀取可能存在部分行失敗的情況,失敗行的錯誤資訊在返回的BatchGetRowResponse中,但並不拋出異常。因此調用BatchGetRow介面時,需要檢查傳回值,可通過BatchGetRowResponse的isAllSucceed方法判斷是否所有行都擷取成功;通過BatchGetRowResponse的getFailedRows方法擷取失敗行的資訊。
樣本
讀取10行,設定版本條件、要讀取的列、過濾器等。
private static void batchGetRow(SyncClient client) {
MultiRowQueryCriteria multiRowQueryCriteria = new MultiRowQueryCriteria(TABLE_NAME);
//加入10個要讀取的行。
for (int i = 0; i < 10; i++) {
PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString("pk" + i));
PrimaryKey primaryKey = primaryKeyBuilder.build();
multiRowQueryCriteria.addRow(primaryKey);
}
//添加條件。
multiRowQueryCriteria.setMaxVersions(1);
multiRowQueryCriteria.addColumnsToGet("Col0");
multiRowQueryCriteria.addColumnsToGet("Col1");
SingleColumnValueFilter singleColumnValueFilter = new SingleColumnValueFilter("Col0",
SingleColumnValueFilter.CompareOperator.EQUAL, ColumnValue.fromLong(0));
singleColumnValueFilter.setPassIfMissing(false);
multiRowQueryCriteria.setFilter(singleColumnValueFilter);
BatchGetRowRequest batchGetRowRequest = new BatchGetRowRequest();
//BatchGetRow支援讀取多個表的資料,一個multiRowQueryCriteria對應一個表的查詢條件,可以添加多個multiRowQueryCriteria。
batchGetRowRequest.addMultiRowQueryCriteria(multiRowQueryCriteria);
BatchGetRowResponse batchGetRowResponse = client.batchGetRow(batchGetRowRequest);
System.out.println("是否全部成功:" + batchGetRowResponse.isAllSucceed());
if (!batchGetRowResponse.isAllSucceed()) {
for (BatchGetRowResponse.RowResult rowResult : batchGetRowResponse.getFailedRows()) {
System.out.println("失敗的行:" + batchGetRowRequest.getPrimaryKey(rowResult.getTableName(), rowResult.getIndex()));
System.out.println("失敗原因:" + rowResult.getError());
}
/**
* 可以通過createRequestForRetry方法再構造一個請求對失敗的行進行重試。此處只給出構造重試請求的部分。
* 推薦的重試方法是使用SDK的自訂重試策略功能,支援對batch操作的部分行錯誤進行重試。設定重試策略後,調用介面處無需增加重試代碼。
*/
BatchGetRowRequest retryRequest = batchGetRowRequest.createRequestForRetry(batchGetRowResponse.getFailedRows());
}
}
詳細代碼請參見BatchGetRow@GitHub。
範圍讀取資料
調用GetRange介面讀取一個範圍內的資料。
GetRange操作支援按照確定範圍進行正序讀取和逆序讀取,可以設定要讀取的行數。如果範圍較大,已掃描的行數或者資料量超過一定限制,會停止掃描,並返回已擷取的行和下一個主鍵資訊。您可以根據返回的下一個主鍵資訊,繼續發起請求,擷取範圍內剩餘的行。
注意事項
GetRange操作遵循最左匹配原則,讀取資料時,依次比較第一主鍵列到第四主鍵列。例如資料表的主鍵包括PK1、PK2、PK3三個主鍵列,讀取資料時,優先比較PK1是否在開始主鍵與結束主鍵的範圍內,如果PK1在設定的主鍵範圍內,則不會再比較其他的主鍵,返回在PK1主鍵範圍內的資料;如果PK1不在設定的主鍵範圍內,則繼續比較PK2是否在開始主鍵與結束主鍵的範圍內,以此類推。
- 掃描的行資料大小之和達到4 MB。
- 掃描的行數等於5000。
- 返回的行數等於最大返回行數。
- 當前剩餘的預留讀輸送量已全部使用,餘量不足以讀取下一條資料。
當使用GetRange掃描的資料量較大時,Tablestore每次請求僅會掃描一次(行數大於5000或者大小大於4 MB停止掃描),超過限制的資料不會繼續返回,需要通過翻頁繼續擷取後面的資料。
參數
參數 | 說明 |
---|---|
tableName | 資料表名稱。 |
direction | 讀取方向。
例如同一表中有兩個主鍵A和B,A<B。如正序讀取[A, B),則按從A至B的順序返回主鍵大於等於A、小於B的行;逆序讀取[B, A),則按從B至A的順序返回大於A、小於等於B的資料。 |
inclusiveStartPrimaryKey | 本次範圍讀取的起始主鍵和結束主鍵,起始主鍵和結束主鍵需要是有效主鍵或者是由INF_MIN和INF_MAX類型組成的虛擬點,虛擬點的列數必須與主鍵相同。 其中INF_MIN表示無限小,任何類型的值都比它大;INF_MAX表示無限大,任何類型的值都比它小。
資料表中的行按主鍵從小到大排序,讀取範圍是一個左閉右開的區間,正序讀取時,返回的是大於等於起始主鍵且小於結束主鍵的所有的行。 |
exclusiveEndPrimaryKey | |
limit | 資料的最大返回行數,此值必須大於 0。 Tablestore按照正序或者逆序返回指定的最大返回行數後即結束該操作的執行,即使該區間內仍有未返回的資料。此時可以通過返回結果中的nextStartPrimaryKey記錄本次讀取到的位置,用於下一次讀取。 |
columnsToGet | 讀取的列集合,列名可以是主鍵列或屬性列。 如果不設定返回的列名,則返回整行資料。 说明
|
maxVersions | 最多讀取的版本數。 说明 maxVersions與timeRange必須至少設定一個。
|
timeRange | 讀取版本號碼範圍或特定版本號碼的資料。更多資訊,請參見TimeRange。 说明 maxVersions與timeRange必須至少設定一個。
timestamp和 時間戳記的單位為毫秒,最小值為0,最大值為Long.MAX_VALUE。 |
filter | 使用過濾器,在服務端對讀取結果再進行一次過濾,只返回符合過濾器中條件的資料行。更多資訊,請參見過濾器。 说明 當columnsToGet和filter同時使用時,執行順序是先擷取columnsToGet指定的列,再在返回的列中進行條件過濾。 |
nextStartPrimaryKey | 根據返回結果中的nextStartPrimaryKey判斷資料是否全部讀取。
|
樣本
- 樣本1按照確定範圍進行正序讀取,判斷nextStartPrimaryKey是否為空白,讀取完範圍內的全部資料。
private static void getRange(SyncClient client, String startPkValue, String endPkValue) { RangeRowQueryCriteria rangeRowQueryCriteria = new RangeRowQueryCriteria(TABLE_NAME); //設定起始主鍵。 PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder(); primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString(startPkValue)); rangeRowQueryCriteria.setInclusiveStartPrimaryKey(primaryKeyBuilder.build()); //設定結束主鍵。 primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder(); primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString(endPkValue)); rangeRowQueryCriteria.setExclusiveEndPrimaryKey(primaryKeyBuilder.build()); rangeRowQueryCriteria.setMaxVersions(1); System.out.println("GetRange的結果為:"); while (true) { GetRangeResponse getRangeResponse = client.getRange(new GetRangeRequest(rangeRowQueryCriteria)); for (Row row : getRangeResponse.getRows()) { System.out.println(row); } //如果NextStartPrimaryKey不為null,則繼續讀取。 if (getRangeResponse.getNextStartPrimaryKey() != null) { rangeRowQueryCriteria.setInclusiveStartPrimaryKey(getRangeResponse.getNextStartPrimaryKey()); } else { break; } } }
- 樣本2
按照第一個主鍵列確定範圍、第二主鍵列從最小值(INF_MIN)到最大值(INF_MAX)進行正序讀取,判斷nextStartPrimaryKey是否為null,讀取完範圍內的全部資料。
private static void getRange(SyncClient client, String startPkValue, String endPkValue) { RangeRowQueryCriteria rangeRowQueryCriteria = new RangeRowQueryCriteria(TABLE_NAME); //設定起始主鍵,以兩個主鍵為例。 PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder(); primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME1, PrimaryKeyValue.fromString(startPkValue));//確定值。 primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME2, PrimaryKeyValue.INF_MIN);//最小值。 rangeRowQueryCriteria.setInclusiveStartPrimaryKey(primaryKeyBuilder.build()); //設定結束主鍵。 primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder(); primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME1, PrimaryKeyValue.fromString(endPkValue));//確定值。 primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME2, PrimaryKeyValue.INF_MAX);//最大值。 rangeRowQueryCriteria.setExclusiveEndPrimaryKey(primaryKeyBuilder.build()); rangeRowQueryCriteria.setMaxVersions(1); System.out.println("GetRange的結果為:"); while (true) { GetRangeResponse getRangeResponse = client.getRange(new GetRangeRequest(rangeRowQueryCriteria)); for (Row row : getRangeResponse.getRows()) { System.out.println(row); } //如果nextStartPrimaryKey不為null,則繼續讀取。 if (getRangeResponse.getNextStartPrimaryKey() != null) { rangeRowQueryCriteria.setInclusiveStartPrimaryKey(getRangeResponse.getNextStartPrimaryKey()); } else { break; } } }
- 樣本3
讀取主鍵範圍為
["pk:2020-01-01.log", "pk:2021-01-01.log")
時Col1列的資料,並對該列的資料執行正則過濾。private static void getRange(SyncClient client) { RangeRowQueryCriteria criteria = new RangeRowQueryCriteria(TABLE_NAME); // 設定主鍵範圍為["pk:2020-01-01.log", "pk:2021-01-01.log"),讀取範圍為左閉右開的區間。 PrimaryKey pk0 = PrimaryKeyBuilder.createPrimaryKeyBuilder() .addPrimaryKeyColumn("pk", PrimaryKeyValue.fromString("2020-01-01.log")) .build(); PrimaryKey pk1 = PrimaryKeyBuilder.createPrimaryKeyBuilder() .addPrimaryKeyColumn("pk", PrimaryKeyValue.fromString("2021-01-01.log")) .build(); criteria.setInclusiveStartPrimaryKey(pk0); criteria.setExclusiveEndPrimaryKey(pk1); // 設定讀取最新版本。 criteria.setMaxVersions(1); // 設定過濾器,當cast<int>(regex(Col1)) > 100時,返回該行。 RegexRule regexRule = new RegexRule("t1:([0-9]+),", VariantType.Type.VT_INTEGER); SingleColumnValueRegexFilter filter = new SingleColumnValueRegexFilter("Col1", regexRule,SingleColumnValueFilter.CompareOperator.GREATER_THAN,ColumnValue.fromLong(100)); criteria.setFilter(filter); while (true) { GetRangeResponse resp = client.getRange(new GetRangeRequest(criteria)); for (Row row : resp.getRows()) { // do something System.out.println(row); } if (resp.getNextStartPrimaryKey() != null) { criteria.setInclusiveStartPrimaryKey(resp.getNextStartPrimaryKey()) } else { break; } } }
詳細代碼請參見GetRange@GitHub。
迭代讀取資料
通過createRangeIterator介面迭代讀取資料。
private static void getRangeByIterator(SyncClient client, String startPkValue, String endPkValue) {
RangeIteratorParameter rangeIteratorParameter = new RangeIteratorParameter(TABLE_NAME);
//設定起始主鍵。
PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString(startPkValue));
rangeIteratorParameter.setInclusiveStartPrimaryKey(primaryKeyBuilder.build());
//設定結束主鍵。
primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString(endPkValue));
rangeIteratorParameter.setExclusiveEndPrimaryKey(primaryKeyBuilder.build());
rangeIteratorParameter.setMaxVersions(1);
Iterator<Row> iterator = client.createRangeIterator(rangeIteratorParameter);
System.out.println("使用Iterator進行GetRange的結果為:");
while (iterator.hasNext()) {
Row row = iterator.next();
System.out.println(row);
}
}
詳細代碼請參見GetRangeByIterator@GitHub。