跳到主要内容

执行建表操作

Tables.TableCreator 是一个便捷的建表工具,旨在简化和标准化表创建过程中所需的各项步骤。 在使用 odps-sdk-java 的过程中,用户可以通过 TableCreator 类来更高效地执行建表操作。

下面我们将依次详细介绍如何使用 TableCreator 类,包括如何获取对象、构建表结构、指定参数等。

获取 TableCreator 对象

使用 TableCreator 前,您需要先获取到 Odps 实例,获取Odps示例的方法参考构建 ODPS 客户端。 同时你必须提供希望创建表所在的表名,以及表的模式(即 TableSchema),如何构建TableSchema可以参考本文构建表结构

以下是获取 TableCreator 对象的示例:

Odps odps = new Odps(...); // 创建 Odps 实例
String projectName = "your_project"; // 项目名称
String tableName = "your_table"; // 表名称
TableSchema tableSchema = new TableSchema(...); // 表结构定义

Tables.TableCreator tableCreator =
odps.tables().newTableCreator(projectName, tableName, tableSchema);

也可以不指定项目名,将在Odps.defaultProject中创建表。

Tables.TableCreator tableCreator = odps.tables().newTableCreator(tableName, tableSchema);

构建表结构

TableSchema 是描述表结构的核心对象,包括列名、数据类型及其其他特性。创建 TableSchema 对象通常需要定义多个 Column 对象,如何构建Column可以参考本文构造列对象

TableSchema 主要包含表的数据列和分区列信息,以下是构建 TableSchema 示例:

Column dataColumn1 = new Column(...);
Column dataColumn2 = new Column(...);
List<Column> moreDataColumns = List.of(...);

Column partitionColumn1 = new Column(...);
Column partitionColumn2 = new Column(...);

TableSchema tableSchema = TableSchema.builder()
.withColumn(dataColumn1)
.withColumn(dataColumn2)
.withColumns(moreDataColumns)
.withPartitionColumn(partitionColumn1)
.withPartitionColumn(partitionColumn2)
.build();

同时TableSchema还拥有几个简单的方法,来加速简单表结构的构建,如:

TableSchema tableSchema = TableSchema.builder()
.withBigintColumn("bigint")
.withStringColumn("string")
.withDoubleColumn("double")
.withDecimalColumn("decimal")
.withDatetimeColumn("datetime")
.withBooleanColumn("boolean")
.build();

构造列对象

Column 对象用于定义每个列的属性,包括列名和数据类型和其他特性。可以使用 Column.newBuilder 方法来构建列对象,示例如下:

Column idColumn = Column.newBuilder("id", TypeInfoFactory.BIGINT).build();
Column nameColumn = Column.newBuilder("name", TypeInfoFactory.STRING).build();

TypeInfoFactory 是一个工厂类,用于创建不同类型的 TypeInfo 对象,如 BIGINTSTRINGDOUBLE 等。 支持 MaxCompute 全部支持的列类型,详情参考数据类型

ColumnBuilder 额外支持配置列的属性,如:

  • 设置列是否为非空notNull 方法
  • 设置列的注释withComment 方法
  • 设置列的默认值withDefaultValue 方法
  • 设置列的生成表达式withGenerateExpression 方法(仅分区列生效)

指定建表参数

TableCreator 提供了多种方法来灵活配置建表参数。以下是 TableCreator 类中可用的主要配置选项:

表的基本信息配置

  • withSchemaName(String schemaName):设置表所在 Schema 的名称(三层模型)。
  • withComment(String comment):为表添加描述信息。
  • ifNotExists():设置在表已存在的情况下不抛出异常,而是忽略创建请求。
  • withHints(Map hints):所执行的 SQL 任务的 hints。
  • withAliases(Map aliases):指定 SQL 语句中的别名。

表类型配置

  • virtualView():将表设置为虚拟视图。仅支持 create view as 语句。
  • transactionTable():将表设置为事务表。
  • deltaTable():将表设置为 Delta 表。Delta 表必须配置主键信息,主键列必须NotNull
  • externalTable():将表设置为外部表。

表属性和选项配置

  • withLifeCycle(Long lifeCycle):设置表的生命周期。
  • withTblProperties(Map tblProperties):设置用户自定义的表属性。
  • autoPartitionBy(GenerateExpression expression, String aliasName):创建 auto-partition 表,需要指定表的生成表达式和分区列名。该方法将使用指定分区信息,覆盖当前 TableSchema 中的分区信息。

聚簇表相关配置

  • withClusterInfo(Table.ClusterInfo clusterInfo):为表配置聚簇信息,用来创建 Hash/Range Cluster 表。

Delta 表相关配置

  • withPrimaryKeys(List primaryKeys):指定表的主键列,仅Delta Table具有限定 distinct 作用。
  • withDeltaTableBucketNum(Integer bucketNum):为 Delta 表设置桶的数量。

外表相关配置

  • withStorageHandler(String storageHandler):按照外部表数据格式指定StorageHandler。
  • withResources(List usingResources):指定使用的外部资源。
  • withLocation(String location):外部表数据存储位置。
  • withSerdeProperties(Map serdeProperties):外部表的授权、压缩、字符解析等相关参数。

视图相关配置

  • withSelectStatement(String selectStatement)create view as/create table as 语句的 select cause。

其他配置

  • withDataHubInfo(DataHubInfo dataHubInfo):创建 DataHub 表的相关信息。
  • debug():启用调试模式,输出执行日志到控制台。

SQL 生成和执行

  • getSQL():生成用于创建表的 SQL 语句。
  • create():执行创建表操作,实际在 ODPS 上创建表。

这些方法可以组合使用,以便根据具体的用例构建复杂的表定义。 通过灵活使用这些方法,您可以根据业务需求定制表的创建。

示例

完成所有配置后,可以通过 getSQL 方法获取创建表的 SQL 语句,或者直接调用 create 方法来执行建表操作:

创建分区表

分区表是用于优化大数据的存储和查询性能的一种表结构,适合存储海量数据。通过为表设置分区列,可以有效地提高查询效率和管理数据。 以下示例演示如何创建一个分区表,定义 p_date 列作为分区列,并在表中添加其他数据列。

public void createPartitionTable() throws OdpsException {
TableSchema schema = TableSchema.builder()
.withColumn(Column.newBuilder("c1", TypeInfoFactory.STRING).build())
.withColumn(Column.newBuilder("c2", TypeInfoFactory.STRING).build())
.withPartitionColumn(Column.newBuilder("p_date", TypeInfoFactory.STRING).build())
.build();
odps.tables().newTableCreator("testProject", "testCreatePartitionTable", schema)
.ifNotExists()
.create();
}

创建 Delta 表

Delta 表是一种用于处理事务性数据的表类型,具有高性能和一致性保证。 下列示例将创建一个 Delta 表,以 BIGINT 类型 'pk' 作为主键,其他列类型为 STRING,分桶数量设置为 16。

public void createDeltaTable() throws OdpsException {
TableSchema schema = TableSchema.builder()
.withColumn(Column.newBuilder("pk", TypeInfoFactory.BIGINT).notNull().build())
.withColumn(Column.newBuilder("c1", TypeInfoFactory.STRING).build())
.withColumn(Column.newBuilder("c2", TypeInfoFactory.STRING).build())
.withColumn(Column.newBuilder("c3", TypeInfoFactory.STRING).build())
.build();

odps.tables().newTableCreator("testProject", "testCreateDeltaTable", schema)
.deltaTable()
.withDeltaTableBucketNum(16)
.withPrimaryKeys(ImmutableList.of("pk"))
.ifNotExists()
.create();
}

创建 Transaction 表

Transaction 表是一种用于处理事务性数据的表类型。 下列示例将创建一个 Transaction 表,使用 struct 类型作为列类型

public void createStructTransactionalTable() throws OdpsException {
StructTypeInfo structTypeInfo = TypeInfoFactory.getStructTypeInfo(
ImmutableList.of("end"), ImmutableList.of(TypeInfoFactory.STRING));

TableSchema schema = TableSchema.builder()
.withColumn(Column.newBuilder("c1", structTypeInfo).build()).build();

odps.tables().newTableCreator("testProject", "testCreateStructTransactionalTable", schema)
.transactionTable()
.ifNotExists()
.create();
}

创建 auto-partition 表

auto-partition 表是一种用于自动生成分区的表类型,当用户不指定分区信息时,系统会根据指定的生成表达式自动生成分区。 下列示例将创建一个 auto-partition 表,其中 p1 列使用 TruncTime 生成表达式,根据 c1 列生成,c1 列存储日期时间数据。

public void createAutoPartitionTable() throws OdpsException {
Column autoParitionCol = Column.newBuilder("p1", TypeInfoFactory.STRING)
.withGenerateExpression(new TruncTime("c1", TruncTime.DatePart.DAY))
.build();
TableSchema schema = TableSchema.builder()
.withColumn(Column.newBuilder("c1", TypeInfoFactory.DATETIME).build())
.withPartitionColumn(autoPar)
.build();
odps.tables().newTableCreator("testProject", "testCreateAutoPartitionTable", schema)
.ifNotExists()
.create();
}

创建 Cluster 表

Cluster 表是用于分布式处理的表,这种表可以通过指定的列进行哈希分区/Row-Range分区,从而实现负载均衡。 通过在创建表时设置 CLUSTERED BY 语句,可以增强数据的存取效率。下面的示例代码演示如何创建一个 Hash Cluster 表,选择 c1c2 两个列作为分区依据,并定义排序方式。

public void createClusterTable() throws OdpsException {
Table.ClusterInfo clusterInfo =
new Table.ClusterInfo(Table.ClusterInfo.ClusterType.HASH,
ImmutableList.of("c1", "c2"), // clustered by 列
ImmutableList.of( // 桶内排序列
new Table.SortColumn("c1", Table.SortColumn.Order.DESC),
new Table.SortColumn("c2", Table.SortColumn.Order.ASC)),
10); // 桶数量

odps.tables().newTableCreator("testProject", "testCreateClusterTable",
TableSchema.builder()
.withColumn(Column.newBuilder("c1", TypeInfoFactory.STRING).build())
.withColumn(Column.newBuilder("c2", TypeInfoFactory.STRING).build())
.build())
.withClusterInfo(clusterInfo).create();
}

创建外表

外表用于连接数据仓库外部的数据源,比如OSS存储或其他数据源。 以下示例展示了如何创建一个外表,指定它的数据存储处理器以及其它相关参数,如位置和序列化属性。

public void testCreateExternalTable() throws OdpsException {
odps.tables().newTableCreator("testProject", "testCreateExternalTable",
TableSchema.builder()
.withColumn(Column.newBuilder("c1", TypeInfoFactory.STRING).build())
.withColumn(Column.newBuilder("c2", TypeInfoFactory.STRING).build())
.build())
.externalTable()
.withStorageHandler("com.aliyun.odps.udf.example.text.TextStorageHandler")
.withResources(ImmutableList.of("odps-udf-example.jar", "another.jar"))
.withLocation("oss://path/to/your/external/data/location/")
.withSerdeProperties(
ImmutableMap.of("odps.text.option.delimiter", "|", "my.own.option", "value"))
.create();
}

创建虚拟视图

虚拟视图是一种用于查询数据源的视图,可以简化数据查询。 以下示例展示了如何创建一个虚拟视图,指定它的查询语句。

public void testCreateView() throws OdpsException {
odps.tables().newTableCreator("testProject", "testCreateView",
TableSchema.builder()
.withColumn(Column.newBuilder("c1", TypeInfoFactory.STRING).build())
.withColumn(Column.newBuilder("c2", TypeInfoFactory.STRING).build())
.build())
.view()
.withSelectStatement("select c1, c2 from testProject.testCreateView")
.create();
}