全部產品
Search
文件中心

Tablestore:寫入資料

更新時間:Jun 30, 2024

Tablestore提供了單行插入、單行更新和批量寫入的寫入方式用於寫入資料到資料表。當要寫入資料到資料表時,您需要指定完整主鍵以及要增刪改的屬性列。在高並發應用中寫入資料時,您可以配置行存在性條件或者列條件實現按照指定條件更新資料。

說明

本文樣本中的pkValue均表示主鍵列值,使用時請根據實際填寫具體資料。

寫入方式

Tablestore提供的資料寫入介面包括PutRow、UpdateRow和BatchWriteRow。寫入資料時,請根據實際情境選擇相應寫入方式。

寫入方式

說明

適用情境

插入單行資料

調用PutRow介面新寫入一行資料。如果該行已存在,則Tablestore會先刪除原行資料(原行的所有列以及所有版本的資料),再寫入新行資料。

適用於要寫入資料較少的情境。

更新單行資料

調用UpdateRow介面更新一行資料,支援增加和刪除一行中的屬性列,刪除屬性列指定版本的資料,或者更新已存在的屬性列值。如果更新的行不存在,則新增一行資料。

適用於更新已寫入資料的情境,例如刪除屬性列、刪除某個資料版本、修改屬性列值等。

批量寫入資料

調用BatchWriteRow介面在一次請求中進行批量寫入操作或者一次對多張表進行寫入。

BatchWriteRow操作由多個PutRow、UpdateRow、DeleteRow子操作組成,構造子操作的過程與使用PutRow介面、UpdateRow介面和DeleteRow介面時相同。

適用於要寫入、刪除或者更新大量資料以及要同時進行增刪改資料的情境。

前提條件

  • 已初始化OTSClient。具體操作,請參見初始化OTSClient

  • 已建立資料表並寫入資料。

插入單行資料

調用PutRow介面新寫入一行資料。如果該行已存在,則先刪除原行資料(原行的所有列以及所有版本的資料),再寫入新行資料。

參數

參數

說明

tableName

資料表名稱。

primaryKey

行的主鍵。主鍵包括主鍵列名、主鍵類型和主索引值。

重要
  • 設定的主鍵個數和類型必須與資料表的主鍵個數和類型一致。

  • 當主鍵為自增列時,只需將自增列的值設定為預留位置。更多資訊,請參見主鍵列自增

condition

使用條件更新,可以設定原行的存在性條件或者原行中某列的列值條件。更多資訊,請參見條件更新

說明
  • RowExistenceExpectation.IGNORE表示無論此行是否存在均會插入新資料,如果之前行已存在,則寫入資料時會覆蓋原有資料。

  • RowExistenceExpectation.EXPECT_EXIST表示只有此行存在時才會插入新資料,寫入資料時會覆蓋原有資料。

  • RowExistenceExpectation.EXPECT_NOT_EXIST表示只有此行不存在時才會插入資料。

column

行的屬性列。每一項的順序是屬性名稱、屬性類型ColumnType(可選)、屬性值ColumnValue、時間戳記timestamp(可選)。

  • 屬性名稱即屬性列的名稱,屬性類型即屬性列的資料類型。更多資訊,請參見命名規則和資料類型

    屬性類型可以是INTEGER、STRING(UTF-8編碼字串)、BINARY、BOOLEAN和DOUBLE五種,分別用ColumnType.INTEGERColumnType.STRINGColumnType.BINARYColumnType.BOOLEANColumnType.DOUBLE表示,其中BINARY類型不可省略,其他類型均可省略。

  • 時間戳記即資料的版本號碼,可以由系統自動產生或者自訂,如果不設定此參數,則預設由系統自動產生。更多資訊,請參見資料版本和生命週期

    • 當由系統自動產生資料的版本號碼時,系統預設將目前時間的毫秒單位時間戳記(從1970-01-01 00:00:00 UTC計算起的毫秒數)作為資料的版本號碼。

    • 當自訂資料的版本號碼時,版本號碼需要為64位的毫秒單位時間戳記且在有效版本範圍內。

樣本

插入資料時由系統自動產生資料版本號碼

以下樣本用於寫入10列屬性列,每列寫入1個版本,由系統自動產生資料的版本號碼(時間戳記)。

private static void putRow(SyncClient client, String pkValue) {
    //構造主鍵。
    PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    primaryKeyBuilder.addPrimaryKeyColumn("pk", PrimaryKeyValue.fromString(pkValue));
    PrimaryKey primaryKey = primaryKeyBuilder.build();
    //設定資料表名稱。
    RowPutChange rowPutChange = new RowPutChange("<TABLE_NAME>", primaryKey);

    //加入一些屬性列。
    for (int i = 0; i < 10; i++) {
        rowPutChange.addColumn(new Column("Col" + i, ColumnValue.fromLong(i)));
    }

    client.putRow(new PutRowRequest(rowPutChange));
}
                    

插入資料時自訂資料版本號碼

以下樣本用於寫入10列屬性列,每列寫入3個版本,自訂資料的版本號碼(時間戳記)。

private static void putRow(SyncClient client, String pkValue) {
    //構造主鍵。
    PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    primaryKeyBuilder.addPrimaryKeyColumn("pk", PrimaryKeyValue.fromString(pkValue));
    PrimaryKey primaryKey = primaryKeyBuilder.build();
    //設定資料表名稱。
    RowPutChange rowPutChange = new RowPutChange("<TABLE_NAME>", primaryKey);

    //加入一些屬性列。
    long ts = System.currentTimeMillis();
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 3; j++) {
            rowPutChange.addColumn(new Column("Col" + i, ColumnValue.fromLong(j), ts + j));
        }
    }

    client.putRow(new PutRowRequest(rowPutChange));
}
                    

插入資料時使用行條件

以下樣本用於當原行不存在時,寫入10列屬性列,每列寫入3個版本,自訂資料的版本號碼(時間戳記)。

private static void putRow(SyncClient client, String pkValue) {
    //構造主鍵。
    PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    primaryKeyBuilder.addPrimaryKeyColumn("pk", PrimaryKeyValue.fromString(pkValue));
    PrimaryKey primaryKey = primaryKeyBuilder.build();
    //設定資料表名稱。
    RowPutChange rowPutChange = new RowPutChange("<TABLE_NAME>", primaryKey);

    //設定條件更新,行條件檢查為期望原行不存在。
    rowPutChange.setCondition(new Condition(RowExistenceExpectation.EXPECT_NOT_EXIST));

    //加入一些屬性列。
    long ts = System.currentTimeMillis();
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 3; j++) {
            rowPutChange.addColumn(new Column("Col" + i, ColumnValue.fromLong(j), ts + j));
        }
    }

    client.putRow(new PutRowRequest(rowPutChange));
}                   

插入資料時使用列條件和行條件

以下樣本用於當原行存在且Col0列的值大於100時,寫入10列屬性列,每列寫入3個版本,自訂資料的版本號碼(時間戳記)。

private static void putRow(SyncClient client, String pkValue) {
    //構造主鍵。
    PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    primaryKeyBuilder.addPrimaryKeyColumn("pk", PrimaryKeyValue.fromString(pkValue));
    PrimaryKey primaryKey = primaryKeyBuilder.build();
    //設定資料表名稱。
    RowPutChange rowPutChange = new RowPutChange("<TABLE_NAME>", primaryKey);

    //設定條件更新,期望原行存在且Col0列的值大於100時寫入資料。
    Condition condition = new Condition(RowExistenceExpectation.EXPECT_EXIST);
    condition.setColumnCondition(new SingleColumnValueCondition("Col0",
            SingleColumnValueCondition.CompareOperator.GREATER_THAN, ColumnValue.fromLong(100)));
    rowPutChange.setCondition(condition);

    //加入一些屬性列。
    long ts = System.currentTimeMillis();
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 3; j++) {
            rowPutChange.addColumn(new Column("Col" + i, ColumnValue.fromLong(j), ts + j));
        }
    }

    client.putRow(new PutRowRequest(rowPutChange));
}
                    

更新單行資料

調用UpdateRow介面更新一行資料,可以增加和刪除一行中的屬性列,刪除屬性列指定版本的資料,或者更新已存在的屬性列的值。如果更新的行不存在,則新增一行資料。

說明

當UpdateRow請求中只包含刪除指定的列且該行不存在時,則該請求不會新增一行資料。

參數

參數

說明

tableName

資料表名稱。

primaryKey

行的主鍵。主鍵包括主鍵列名、主鍵類型和主索引值。

重要

設定的主鍵個數和類型必須和資料表的主鍵個數和類型一致。

condition

使用條件更新,可以設定原行的存在性條件或者原行中某列的列值條件。更多資訊,請參見條件更新

column

更新的屬性列。

  • 增加或更新資料時,需要設定屬性名稱、屬性值、屬性類型(可選)、時間戳記(可選)。

    屬性名稱即屬性列的名稱,屬性類型即屬性列的資料類型。更多資訊,請參見命名規則和資料類型

    時間戳記即資料的版本號碼,可以由系統自動產生或者自訂,如果不設定此參數,則預設由系統自動產生。更多資訊,請參見資料版本和生命週期

    • 當由系統自動產生資料的版本號碼時,系統預設將目前時間的毫秒單位時間戳記(從1970-01-01 00:00:00 UTC計算起的毫秒數)作為資料的版本號碼。

    • 當自訂資料的版本號碼時,版本號碼需要為64位的毫秒單位時間戳記且在有效版本範圍內。

  • 刪除屬性列特定版本的資料時,只需要設定屬性名稱和時間戳記。

    時間戳記是64位整數,單位為毫秒,表示某個特定版本的資料。

  • 刪除屬性列時,只需要設定屬性名稱。

    說明

    刪除一行的全部屬性列不等同於刪除該行,如果需要刪除該行,請使用DeleteRow操作。

樣本

更新資料時不使用條件

以下樣本用於更新一些列,刪除某列的某一版本資料以及刪除某列。

private static void updateRow(SyncClient client, String pkValue) {
    //構造主鍵。
    PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString(pkValue));
    PrimaryKey primaryKey = primaryKeyBuilder.build();
    //設定資料表名稱。
    RowUpdateChange rowUpdateChange = new RowUpdateChange("<TABLE_NAME>", primaryKey);

    //更新一些列。
    for (int i = 0; i < 10; i++) {
        rowUpdateChange.put(new Column("Col" + i, ColumnValue.fromLong(i)));
    }

    //刪除某列的某一版本。
    rowUpdateChange.deleteColumn("Col10", 1465373223000L);

    //刪除某一列。
    rowUpdateChange.deleteColumns("Col11");

    client.updateRow(new UpdateRowRequest(rowUpdateChange));
}                   

更新資料時使用列條件和行條件

以下樣本用於當原行存在且Col0列的值大於100時更新資料。

private static void updateRow(SyncClient client, String pkValue) {
    //構造主鍵。
    PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString(pkValue));
    PrimaryKey primaryKey = primaryKeyBuilder.build();
    //設定資料表名稱。
    RowUpdateChange rowUpdateChange = new RowUpdateChange("<TABLE_NAME>", primaryKey);

    //設定條件更新,期望原行存在且Col0列的值大於100時更新資料。
    Condition condition = new Condition(RowExistenceExpectation.EXPECT_EXIST);
    condition.setColumnCondition(new SingleColumnValueCondition("Col0",
            SingleColumnValueCondition.CompareOperator.GREATER_THAN, ColumnValue.fromLong(100)));
    rowUpdateChange.setCondition(condition);

    //更新一些列。
    for (int i = 0; i < 10; i++) {
        rowUpdateChange.put(new Column("Col" + i, ColumnValue.fromLong(i)));
    }

    //刪除某列的某一版本。
    rowUpdateChange.deleteColumn("Col10", 1465373223000L);

    //刪除某一列。
    rowUpdateChange.deleteColumns("Col11");

    client.updateRow(new UpdateRowRequest(rowUpdateChange));
}         

批量寫入資料

調用BatchWriteRow介面在一次請求中進行批量寫入操作或者一次對多張表進行寫入。

BatchWriteRow操作由多個PutRow、UpdateRow、DeleteRow子操作組成,構造子操作的過程與使用PutRow介面、UpdateRow介面和DeleteRow介面時相同。

BatchWriteRow的各個子操作獨立執行,Tablestore會分別返回各個子操作的執行結果。

注意事項

  • 由於批量寫入可能存在部分行失敗的情況,失敗行的Index及錯誤資訊在返回的BatchWriteRowResponse中,但並不拋出異常。因此調用BatchWriteRow介面時,需要檢查傳回值,可通過BatchWriteRowResponse的isAllSucceed方法判斷是否全部成功;如果不檢查傳回值,則可能會忽略掉部分操作的失敗。

  • 當服務端檢查到某些操作出現參數錯誤時,BatchWriteRow介面可能會拋出參數錯誤的異常,此時該請求中所有的操作都未執行。

樣本

以下樣本中一次BatchWriteRow請求包含2個PutRow操作、1個DeleteRow操作和1個UpdateRow操作用於更新表中資料。

private static void batchWriteRow(SyncClient client) {
    BatchWriteRowRequest batchWriteRowRequest = new BatchWriteRowRequest();

    //構造rowPutChange1。
    PrimaryKeyBuilder pk1Builder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    pk1Builder.addPrimaryKeyColumn("pk", PrimaryKeyValue.fromString("pk1"));
    //設定資料表名稱。
    RowPutChange rowPutChange1 = new RowPutChange("<TABLE_NAME>", pk1Builder.build());
    //添加一些列。
    for (int i = 0; i < 10; i++) {
        rowPutChange1.addColumn(new Column("Col" + i, ColumnValue.fromLong(i)));
    }
    //添加到batch操作中。
    batchWriteRowRequest.addRowChange(rowPutChange1);

    //構造rowPutChange2。
    PrimaryKeyBuilder pk2Builder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    pk2Builder.addPrimaryKeyColumn("pk", PrimaryKeyValue.fromString("pk2"));
    //設定資料表名稱。
    RowPutChange rowPutChange2 = new RowPutChange("<TABLE_NAME>", pk2Builder.build());
    //添加一些列。
    for (int i = 0; i < 10; i++) {
        rowPutChange2.addColumn(new Column("Col" + i, ColumnValue.fromLong(i)));
    }
    //添加到batch操作中。
    batchWriteRowRequest.addRowChange(rowPutChange2);

    //構造rowUpdateChange。
    PrimaryKeyBuilder pk3Builder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    pk3Builder.addPrimaryKeyColumn("pk", PrimaryKeyValue.fromString("pk3"));
    //設定資料表名稱。
    RowUpdateChange rowUpdateChange = new RowUpdateChange("<TABLE_NAME>", pk3Builder.build());
    //添加一些列。
    for (int i = 0; i < 10; i++) {
        rowUpdateChange.put(new Column("Col" + i, ColumnValue.fromLong(i)));
    }
    //刪除一列。
    rowUpdateChange.deleteColumns("Col10");
    //添加到batch操作中。
    batchWriteRowRequest.addRowChange(rowUpdateChange);

    //構造rowDeleteChange。
    PrimaryKeyBuilder pk4Builder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    pk4Builder.addPrimaryKeyColumn("pk", PrimaryKeyValue.fromString("pk4"));
    //設定資料表名稱。
    RowDeleteChange rowDeleteChange = new RowDeleteChange("<TABLE_NAME>", pk4Builder.build());
    //添加到batch操作中。
    batchWriteRowRequest.addRowChange(rowDeleteChange);

    BatchWriteRowResponse response = client.batchWriteRow(batchWriteRowRequest);

    System.out.println("是否全部成功:" + response.isAllSucceed());
    if (!response.isAllSucceed()) {
        for (BatchWriteRowResponse.RowResult rowResult : response.getFailedRows()) {
            System.out.println("失敗的行:" + batchWriteRowRequest.getRowChange(rowResult.getTableName(), rowResult.getIndex()).getPrimaryKey());
            System.out.println("失敗原因:" + rowResult.getError());
        }
        /**
         * 可以通過createRequestForRetry方法再構造一個請求對失敗的行進行重試。此處只給出構造重試請求的部分。
         * 推薦的重試方法是使用SDK的自訂重試策略功能,支援對batch操作的部分行錯誤進行重試。設定重試策略後,調用介面處無需增加重試代碼。
         */
        BatchWriteRowRequest retryRequest = batchWriteRowRequest.createRequestForRetry(response.getFailedRows());
    }
}            

詳細代碼請參見BatchWriteRow@GitHub

常見問題

相關文檔

  • 當要在高並發應用中實現按照指定條件更新資料時,您可以通過條件更新實現。更多資訊,請參見條件更新

  • 當要為線上應用提供即時統計功能時,例如統計文章的PV(即時瀏覽量)等,您可以通過原子計數器實現。更多資訊,請參見原子計數器

  • 當要進行單行寫或多行寫的原子操作,您可以通過局部事務實現。更多資訊,請參見局部事務

  • 寫入資料後,即可根據需要讀取或者刪除表中資料。更多資訊,請參見讀取資料刪除資料