天天看點

Tablestore入門手冊--表(Table)管理表管理接口概述createTabledeleteTablelistTableupdateTabledescribeTable專家服務

表管理接口概述

API 描述
createTable 建立表
deleteTable 删除表
listTable 列出執行個體下的所有表
updateTable 更新表(在表被建立之後,動态的更改表的配置或預留吞吐量)
describeTable 擷取表的詳細資訊

上述API操作是Tablestore最基礎的API。官方提供了Java、Go、Node.js、Python、PHP、C#、C++語言的SDK。

建立表可以在控制台進行。在使用API進行建立的時候,需要指定表的配置資訊和預留吞吐量等資訊。

說明:

  • 表格建立好後服務端有初始化時間,需要等待幾秒鐘才能對表進行讀寫,否則會出現異常

表限制

參數說明

建立表的參數主要包括如下幾部分:

  • TableMeta:  表的結構資訊,包含表的名稱以及表的主鍵定義
  • TableOptions:  表的配置選項,用于配置TTL、MaxVersions等
  • ReservedThroughput:表的預留讀寫吞吐量設定

表結構 TableMeta

參數 定義 說明
TableName 表名
List 表的主鍵定義
  • 注意: 最多可設定 4 個主鍵,主鍵的配置及順序一旦設定便不可修改。
  • 表格存儲可包含多個主鍵列。主鍵列是有順序的,與使用者添加的順序相同,例如, PRIMARY KEY (A, B, C) 與 PRIMARY KEY (A, C, B) 是不同的兩個主鍵結構。表格存儲會按照主鍵的大小為行排序,具體參見 表格存儲資料模型和查詢操作
  • 第一列主鍵作為分片鍵。分片鍵相同的資料會存放在同一個分片内,是以相同分片鍵下最好不要超過 10 G 以上資料,否則會導緻單分片過大,無法分裂。另外,資料的讀/寫通路最好在不同的分片鍵上均勻分布,有利于負載均衡。
  • 屬性列不需要定義。表格存儲每行的資料列都可以不同,屬性列的列名在寫入時指定。

表配置 TableOptions

TTL TimeToLive,資料存活時間
  • 機關:秒。
  • 如果期望資料永不過期,TTL 可設定為 -1。
  • 資料是否過期是根據資料的時間戳、目前時間、表的 TTL三者進行判斷的。

    目前時間 - 資料的時間戳 > 表的 TTL

    時,資料會過期并被清理。
  • 在使用 TTL 功能時需要注意寫入時是否指定了時間戳,以及指定的時間戳是否合理。如需指定時間戳,建議設定MaxTimeDeviation。
MaxVersions 每個屬性列保留的最大版本數
  • 如果寫入的版本數超過 MaxVersions,服務端隻會保留 MaxVersions 中指定的最大的版本。
MaxTimeDeviation 寫入資料的時間戳與系統目前時間的偏差允許最大值
  • 該參數絕大多數情況下使用者使用不到,使用服務端的預設值即可。
  • 預設情況下系統會為新寫入的資料生成一個時間戳,資料自動過期功能需要根據這個時間戳判斷資料是否過期。使用者也可以指定寫入資料的時間戳。如果使用者寫入的時間戳非常小,與目前時間偏差已經超過了表上設定的 TTL 時間,寫入的資料會立即過期。設定 MaxTimeDeviation 可以避免這種情況。
  • 可在建表時指定,也可通過 UpdateTable 接口修改。

預留吞吐量 ReservedThroughtput

  • ReservedThroughtput表的預留讀/寫吞吐量配置。
    • 設定 ReservedThroughtput 後,表格存儲按照您預留讀/寫吞吐量進行計費。
    • 當 ReservedThroughtput 大于 0 時,表格存儲會按照預留量和持續時間進行計費,超出預留的部分進行按量計費。更多資訊參見 計費 ,以免産生未期望的費用。
    • 預設值為 0,即完全按量計費。
    • 容量型執行個體的預留讀/寫吞吐量隻能設定為 0,不允許預留。

Java代碼示例

// 建立普通表(不使用索引等功能)
public void createTable() {
    TableMeta tableMeta = new TableMeta(TABLE_NAME);
    // 為主表添加主鍵列。
    tableMeta.addPrimaryKeyColumn(new PrimaryKeySchema("pk_1", PrimaryKeyType.STRING));
    tableMeta.addPrimaryKeyColumn(new PrimaryKeySchema("pk_2", PrimaryKeyType.INTEGER));
    tableMeta.addPrimaryKeyColumn(new PrimaryKeySchema("pk_3", PrimaryKeyType.BINARY));
    // 設定該主鍵為自增列
    tableMeta.addPrimaryKeyColumn(new PrimaryKeySchema("pk_4", PrimaryKeyType.INTEGER, PrimaryKeyOption.AUTO_INCREMENT));

    // 資料的過期時間,機關秒, -1代表永不過期,例如設定過期時間為一年, 即為 365 * 24 * 3600。
    int timeToLive = -1;
    // 儲存的最大版本數,設定為3即代表每列上最多儲存3個最新的版本。(如果使用索引,maxVersions隻能等于1)
    int maxVersions = 3;

    TableOptions tableOptions = new TableOptions(timeToLive, maxVersions);
    CreateTableRequest request = new CreateTableRequest(tableMeta, tableOptions);
    // 設定讀寫預留值,容量型執行個體隻能設定為0,高性能執行個體可以設定為非零值。
    request.setReservedThroughput(new ReservedThroughput(new CapacityUnit(0, 0)));
    client.createTable(request);
}           

表設計相關技巧

分區鍵選擇

表格存儲Tablestore第一個主鍵是分區鍵,決定了資料分布式存儲的位置。分區鍵的選擇決定了資料是否均勻散列在不同的後端伺服器上。散列是分布式資料庫中常見的問題之一,資料的散列能夠避免熱點問題。是以在選擇主鍵的時候,首先要選好分區鍵。其中比較常用的兩種方式如下:

  1. 分區鍵可以選擇業務上比較分散的Key放到第一列,如userID、DeviceId等。如果每個使用者資料分布嚴重不均勻,則需要另外選擇其它字段。
  2. 如果分區鍵不好設計,可以對想要當做分區鍵的值拼接MD5,這樣能夠保證資料散列。

更多的設計技巧見兩篇表設計實踐。  

表設計的最佳實踐

 、

表設計實踐

資料生命周期TTL設計

資料生命周期(Time To Live,簡稱 TTL)是資料表的一個特性,即資料的存活時間,機關為秒。表格存儲會在背景對超過存活時間的資料進行清理,以減少使用者的資料存儲空間,降低存儲成本。

TTL特性能夠實作資料過期自動删除,是以在很多場景能夠用到,這些場景中随着時間的流逝資料的價值會降低,特别适合TTL。

  1. 輿情監控。如果使用者隻關心最近3個月的資訊,是以超過3個月的資料可以自動删除。
  2. 物流軌迹。物流軌迹的記錄資訊在使用者收到貨物後就失去了其大部分的價值,是以可以設定1個月的TTL,來節省大量的存儲費用。
  3. 系統日志。系統的運作日志大多數隻有在系統出問題時候才會檢視,而随着時間流逝,很早之前的系統日志也就失去了存在的價值,而這部分資料存儲在資料庫中會占用存儲成本,設定合适的TTL能夠自動将之前的資料删除。

TTL暫時僅支援主表,索引等還暫時不支援TTL特性。是以如果使用了二級索引或者多元索引,需要主表的TTL=-1,即永久不會失效,對于已經建立好表的使用者,可以通過 UpdateTable 接口動态更改主表的 TTL。

Java 示例代碼

public void updateTTL() {
        UpdateTableRequest request = new UpdateTableRequest(TABLE_NAME);
        int ttl = -1;
        request.setTableOptionsForUpdate(new TableOptions(ttl));
        client.updateTable(request);
    }           

主鍵自增

主鍵列自增功能是指若使用者指定某一列主鍵為自增列,在其寫入資料時,表格存儲會自動為使用者在這一列産生一個新的值,且這個值為同一個分區鍵下該列的最大值。

主鍵自增列的功能特性主要有生成數字ID且ID嚴格遞增保證順序,這個特性決定了許多場景能夠使用。

  • 如電商網站的商品 ID、大型網站的使用者 ID等,這些場景中數值越大,表示該商品、使用者越新。
  • 如論壇文章的 ID、聊天工具的消息 ID等消息保序的場景,這些場景需要嚴格保證消息遞增,不然使用者讀取到的順序就會亂序。舉個例子,假如使用者發朋友圈場景,使用者在1點5分11.1秒時刻發送了一個朋友圈記錄a,另一個使用者在1點5分11.2秒發送了一個朋友圈記錄b,則需要嚴格保證記錄b的id比記錄a的id大。主鍵自增在聊天系統IM中的應用見  Table Store主鍵列自增功能在IM系統中的應用

主鍵自增的一些限制:

  • 表格存儲支援多個主鍵,第一個主鍵為分區鍵,分區鍵不允許設定為自增列,其它任一主鍵都可以設定為自增列。
  • 每張表最多隻允許設定一個主鍵為自增列。
  • 屬性列不能設定為自增列。
  • 僅支援在建立表的時候指定自增列,對于已存在的表不支援建立自增列。

Java示例代碼

// 主鍵自增 建立主表
public void createTableWithPKAutoIncrement() {
    TableMeta tableMeta = new TableMeta(TABLE_NAME + "AUTO_INCREMENT");
    tableMeta.addPrimaryKeyColumn(new PrimaryKeySchema("pk_1", PrimaryKeyType.STRING));
    // 設定該主鍵為自增列
    tableMeta.addPrimaryKeyColumn(new PrimaryKeySchema("pk_autoI_increment", PrimaryKeyType.INTEGER, PrimaryKeyOption.AUTO_INCREMENT));
    tableMeta.addPrimaryKeyColumn(new PrimaryKeySchema("pk_3", PrimaryKeyType.INTEGER));

    TableOptions tableOptions = new TableOptions(-1, 1);
    CreateTableRequest request = new CreateTableRequest(tableMeta, tableOptions);
    client.createTable(request);
}

// 自增列的資料插入
public void putRow(){
    PrimaryKey primaryKey = PrimaryKeyBuilder.createPrimaryKeyBuilder()
        .addPrimaryKeyColumn("pk_1", PrimaryKeyValue.fromString("test1"))
        .addPrimaryKeyColumn("pk_auto_increment", PrimaryKeyValue.AUTO_INCREMENT)
        .addPrimaryKeyColumn("pk_3", PrimaryKeyValue.fromLong(100))
        .build();
    RowPutChange rowPutChange = new RowPutChange(TABLE_NAME , primaryKey);
    rowPutChange.addColumn("attr_1", ColumnValue.fromLong(100));
    PutRowRequest request = new PutRowRequest(rowPutChange);
    client.putRow(request);
}           

删除表,隻需要指定表名字即可。

  • 如果表中建立了多元索引,需要先删除多元索引才可以删除表。

public void deleteTable() {
        DeleteTableRequest request = new DeleteTableRequest(TABLE_NAME);
        client.deleteTable(request);
    }           

該API能夠列出目前執行個體下已建立的所有表的表名。

public void listTable() {
        ListTableResponse response = client.listTable();
        System.out.println("表的清單如下:");
        for (String tableName : response.getTableNames()) {
            System.out.println(tableName);
        }
    }              

該API能夠動态的更改表的配置或預留吞吐量。可以隻修改配置或隻修改預留吞吐量,也可以一起修改。

  • 該API調用頻率有限制,為每 2分鐘1次。

public void updateTable() {
        UpdateTableRequest request = new UpdateTableRequest(TABLE_NAME);
        // 修改預留吞吐
        request.setReservedThroughputForUpdate(new ReservedThroughput(new CapacityUnit(0, 0)));
        // 修改表的最大保留版本、TTL等
        request.setTableOptionsForUpdate(new TableOptions(-1, 1));
        client.updateTable(request);
    }           

該API可以獲得表的結構資訊(TableMeta)、配置資訊(TableOptions)和預留讀/寫吞吐量的情(ReservedThroughputDetails,包括調整時間)、表分區資訊等, 如圖所示。

Tablestore入門手冊--表(Table)管理表管理接口概述createTabledeleteTablelistTableupdateTabledescribeTable專家服務

public void describeTable() {
        DescribeTableRequest request = new DescribeTableRequest(TABLE_NAME);
        DescribeTableResponse response = client.describeTable(request);
        TableMeta tableMeta = response.getTableMeta();
        System.out.println("表的名稱:" + tableMeta.getTableName());

        System.out.println("表的主鍵:");
        for (PrimaryKeySchema schema : tableMeta.getPrimaryKeyList()) {
            System.out.println("\t主鍵名字:" + schema.getName() + "\t主鍵類型:" + schema.getType()
                + "\t自增列:" + (schema.getOption() == null ? "false" : schema.getOption().equals(PrimaryKeyOption.AUTO_INCREMENT)));
        }

        System.out.println("預定義列資訊:");
        for (DefinedColumnSchema schema : tableMeta.getDefinedColumnsList()) {
            System.out.println("\t主鍵名字:" + schema.getName() + "\t主鍵類型:" + schema.getType());
        }

        System.out.println("二級索引資訊:");
        for (IndexMeta meta : response.getIndexMeta()) {
            System.out.println("\t索引名字:" + meta.getIndexName());
            System.out.println("\t\t索引類型:" + meta.getIndexType());
            System.out.println("\t\t索引主鍵:" + meta.getPrimaryKeyList());
            System.out.println("\t\t索引預定義列:" + meta.getDefinedColumnsList());
        }

        TableOptions tableOptions = response.getTableOptions();
        System.out.println("TableOptions:");
        System.out.println("\t表的TTL:" + tableOptions.getTimeToLive());
        System.out.println("\t表的MaxVersions:" + tableOptions.getMaxVersions());

        ReservedThroughputDetails rtd = response.getReservedThroughputDetails();
        System.out.println("預留吞吐量:");
        System.out.println("\t讀:" + rtd.getCapacityUnit().getReadCapacityUnit());
        System.out.println("\t寫:" + rtd.getCapacityUnit().getWriteCapacityUnit());
        System.out.println("\t最近上調時間: " + new Date(rtd.getLastIncreaseTime() * 1000));
        System.out.println("\t最近下調時間: " + new Date(rtd.getLastDecreaseTime() * 1000));

        List<PrimaryKey> shardSplits = response.getShardSplits();
        System.out.println("表分區資訊:");
        for (PrimaryKey primaryKey : shardSplits) {
            System.out.println("\t分裂點資訊: " + primaryKey.getPrimaryKeyColumnsMap());
        }
    }           

專家服務

如有疑問或者需要更好的線上支援,歡迎加入釘釘群:“表格存儲公開交流群”(群号:23307953)。群内提供免費的線上專家服務,歡迎掃碼加入。

Tablestore入門手冊--表(Table)管理表管理接口概述createTabledeleteTablelistTableupdateTabledescribeTable專家服務