创建和使用时间列分区表

本文档介绍如何创建和使用按 DATETIMESTAMPDATETIME 列分区的表。如需了解提取时间分区表,请参阅创建和使用提取时间分区表。如需了解整数范围分区表,请参阅创建和使用整数范围分区表

创建分区表后,您可以执行下列操作:

  • 控制对表数据的访问权限
  • 获取有关分区表的信息
  • 列出数据集中的分区表
  • 使用元表获取分区表元数据

如需详细了解如何管理分区表(包括更新分区表属性、复制分区表和删除分区表),请参阅管理分区表

限制

分区表会受到下列限制的约束:

  • 分区列必须是标量 DATETIMESTAMPDATETIME 列。虽然列模式可以是 REQUIREDNULLABLE,但不能是 REPEATED(基于数组)。
  • 此外,分区列必须是顶级字段。不能将 RECORD (STRUCT) 中的叶字段用作分区列。
  • 不能使用旧版 SQL 查询分区表,也不能将查询结果写入分区表中。

每小时、每月和每年分区表还进一步受到下列限制的约束:

  • bq 命令行工具中的 bq partition 命令不受支持。

创建分区表

您可以通过以下方式创建分区表:

表命名

在 BigQuery 中创建表时,数据集中每个表的名称都必须具有唯一性。表名称可:

  • 包含最多 1024 个字符。
  • 包含类别 L(字母)、M(符号)、N(数字)、Pc(连接符,包括下划线)、Pd(短划线)、Zs(空格)中的 Unicode 字符。如需了解详情,请参阅常规类别

例如,以下都是有效的表名称:table-01ग्राहक00_お客様étudiant

所需权限

如需创建表,您至少必须具有以下权限:

  • bigquery.tables.create:创建表的权限
  • bigquery.tables.updateData:使用加载作业、查询作业或复制作业向表中写入数据
  • bigquery.jobs.create:用于运行向表中写入数据的查询作业、加载作业或复制作业

如需访问向表中写入的数据,可能还需要其他权限,例如 bigquery.tables.getData

以下预定义的 IAM 角色同时包含 bigquery.tables.createbigquery.tables.updateData 权限:

  • bigquery.dataEditor
  • bigquery.dataOwner
  • bigquery.admin

以下预定义的 IAM 角色包含 bigquery.jobs.create 权限:

  • bigquery.user
  • bigquery.jobUser
  • bigquery.admin

此外,如果用户具有 bigquery.datasets.create 权限,则当该用户创建数据集时,系统会为其授予该数据集的 bigquery.dataOwner 访问权限。借助 bigquery.dataOwner 访问权限,用户可以在数据集内创建和更新表。

如需详细了解 BigQuery 中的 IAM 角色和权限,请参阅预定义的角色和权限

每日分区与每小时、每月或每年分区

使用 TIMESTAMPDATETIMEDATE 列对数据进行分区时,您可以根据数据和需求以每天、每小时、每个月或每年粒度创建分区。

每日分区是默认分区类型;与聚簇操作一起使用时,该分区适用于大多数 BigQuery 使用场景。具体而言,如果您的数据分布于多个日期范围内,或者如果数据随时间不断增加,则每日分区是更好的选择。如果您的数据覆盖的日期范围很广,则每日分区可确保您保持在表的分区限制之下。

如果您的表包含大量数据,且这些数据覆盖一个较短的日期范围(时间戳值通常小于六个月),请选择每小时分区。借助每小时分区,您可以按小时级的粒度处理数据;例如,在附加、截断或删除特定分区中的数据时。

如果您的表每天包含的数据量相对较少,但覆盖的日期范围很广,请选择每月或每年分区。如果您的工作流需要频繁更新或添加覆盖较广日期范围的行(例如超过 500 个日期),我们也建议您使用此分区选项。在上述情况下,对时间戳、日期或日期时间分区列使用每月或每年分区以及聚簇操作能够实现最佳性能。如需了解详情和查看示例,请参阅将时间单位分区与聚簇操作搭配使用

创建含架构定义的空分区表

您无法创建不含架构定义的空分区表。必须使用架构,才能确定用于创建分区的列。

创建具有架构定义的空分区表时,您可以执行以下操作:

  • 使用 bq 命令行工具以内嵌方式提供架构。
  • 使用 bq 命令行工具指定 JSON 架构文件。
  • 调用 API 的 tables.insert 方法时,在表资源中提供架构。

如需详细了解如何指定表架构,请参阅指定架构

创建分区表后,您可以执行以下操作:

  • 向其中加载数据。
  • 向其中写入查询结果。
  • 向其中复制数据。

如需创建带架构定义的空分区表,请按如下所述操作:

控制台

  1. 在导航面板的资源部分中,展开您的项目并选择数据集。

  2. 在窗口右侧的详细信息面板中,点击创建表

  3. 创建表面板的来源部分,执行以下操作:

    • 基于以下数据创建表部分,选择空表
  4. 目标部分中执行如下设置:

    • 对于数据集名称,选择相应的数据集,然后在表名称字段中输入要创建的表的名称。
    • 确认表类型设置为原生表
  5. 架构部分中,输入架构定义。

    • 通过以下方式,手动输入架构信息:

      • 启用以文本形式修改,并以 JSON 数组格式输入表架构。

      • 使用添加字段手动输入架构。

  6. 分区和聚簇设置中,点击无分区,选择按字段分区 (Partition by field),然后选择 DATETIMESTAMPDATETIME 列。如果架构不包含 DATETIMESTAMPDATETIME 列,则此选项不可用。

  7. (可选)在分区过滤条件中,点击需要分区过滤条件框,以要求用户添加 WHERE 子句来指定要查询的分区。要求分区过滤条件有可能减少费用并提高性能。如需了解详情,请参阅查询分区表

  8. (可选)点击高级选项,然后在加密部分,点击客户管理的密钥以使用 Cloud Key Management Service 密钥。如果保留 Google 管理的密钥设置,BigQuery 将对静态数据进行加密

  9. 点击创建表

SQL

借助数据定义语言 (DDL) 语句,您可以使用标准 SQL 查询语法创建和修改表和视图。

详细了解如何使用数据定义语言语句

要在 Cloud Console 中使用 DDL 语句创建分区表,请执行以下操作:

  1. 在 Cloud Console 中打开 BigQuery 页面。

    转到 BigQuery 页面

  2. 点击编写新查询

  3. 查询编辑器文本区域中,输入您的 CREATE TABLE DDL 语句

    以下查询会创建一个名为 newtable 的表,该表按 transaction_date DATE 列进行每日分区且分区到期时间设置为 3 天。

     CREATE TABLE
       mydataset.newtable (transaction_id INT64,
         transaction_date DATE)
     PARTITION BY
       transaction_date
     OPTIONS
       ( partition_expiration_days=3,
         description="a table partitioned by transaction_date" )

    以下查询会创建相同的表,但这次执行的是每小时分区。请注意,使用 TIMESTAMP_TRUNC 在小时标记处划分时间戳:

     CREATE TABLE
       mydataset.newtable (transaction_id INT64,
         transaction_ts TIMESTAMP)
     PARTITION BY
       TIMESTAMP_TRUNC(transaction_ts, HOUR)
     OPTIONS
       ( partition_expiration_days=3,
         description="a table partitioned by transaction_ts" )

    以下查询会创建相同的表,但这次执行的是每月分区。请注意,使用 TIMESTAMP_TRUNC 在月标记处划分时间戳:

     CREATE TABLE
       mydataset.newtable (transaction_id INT64,
         transaction_ts TIMESTAMP)
     PARTITION BY
       TIMESTAMP_TRUNC(transaction_ts, MONTH)
     OPTIONS
       ( partition_expiration_days=3,
         description="a table partitioned by transaction_ts" )

    以下查询会创建相同的表,但这次执行的是每年分区。请注意,使用 TIMESTAMP_TRUNC 在年标记处划分时间戳:

     CREATE TABLE
       mydataset.newtable (transaction_id INT64,
         transaction_ts TIMESTAMP)
     PARTITION BY
       TIMESTAMP_TRUNC(transaction_ts, YEAR)
     OPTIONS
       ( partition_expiration_days=3,
         description="a table partitioned by transaction_ts" )

  4. 点击运行。查询完成后,该表将显示在资源窗格中。

bq

bq mk 命令与 --table 标志(或 -t 快捷方式)、--schema 标志和 --time_partitioning_field 标志结合使用。您可以通过内嵌方式或通过 JSON 架构文件提供表的架构定义。

可选参数包括 --expiration--description--time_partitioning_expiration--destination_kms_key--require_partition_filter--time_partitioning_type--label

如果您要在非默认项目中创建表,请按以下格式将相应项目 ID 添加到数据集中:project_id:dataset

本文未演示 --destination_kms_key。如需详细了解如何使用此标志,请参阅使用 Cloud Key Management Service 密钥保护数据

输入以下命令可创建带架构定义的空分区表:

bq mk --table \
--expiration integer1 \
--schema schema \
--time_partitioning_field column \
--time_partitioning_type unit_time \
--time_partitioning_expiration integer2 \
--[no]require_partition_filter \
--description "description" \
--label key:value, key:value \
project_id:dataset.table

请替换以下内容:

  • integer1 是表的默认生命周期(以秒为单位)。 最小值为 3600 秒(一小时)。过期时间以当前世界协调时间 (UTC) 加上这个整数值为准。如果您在创建时间单位分区表时设置了该表的过期时间,则系统会忽略数据集的默认表过期时间设置。如果设置了此值,系统将在指定的时间后删除表和所有分区。
  • schema 是采用 field:data_type, field:data_type 格式的内嵌架构定义,或者是本地机器上 JSON 架构文件的路径。
  • column 是用于创建分区的 TIMESTAMPDATETIMEDATE 列的名称。
  • unit_time 可以是 DAYHOURMONTHYEAR,具体取决于所需的时间单位分区粒度。如果未指定 time_partitioning_type,则此变量默认为 DAY
  • integer2 是表分区的默认生命周期(以秒为单位)。它没有最小值。过期时间以分区的日期加上这个整数值为准。分区过期时间虽然与表的过期时间无关,但它不会替换表的过期时间。如果设置的分区过期时间超过了表的过期时间,则以表的过期时间为准。
  • description 是加英文引号的表说明。
  • key:value 是代表标签key:value 对。 您可以使用英文逗号分隔列表输入多个标签。
  • project_id 是项目 ID。
  • dataset 是您的项目中的数据集。
  • table 是您要创建的分区表的名称。

使用 bq 命令行工具指定架构时,您不能添加 RECORD (STRUCT) 类型和列说明,也不能指定列的模式。所有模式均默认为 NULLABLE。如需添加说明、模式和 RECORD 类型,请改为提供 JSON 架构文件

示例:

输入以下命令,在默认项目的 mydataset 中创建一个名为 mypartitionedtable 的每小时分区表。分区的过期时间设置为 86400 秒(1 天),表的过期时间设置为 2592000(1 个月/30 天),说明设置为 This is my partitioned table,标签设置为 organization:development。该命令使用 -t 快捷方式代替 --table

--require_partition_filter 标志用于要求用户添加 WHERE 子句来指定要查询的分区。要求分区过滤条件有可能减少费用并提高性能。如需了解详情,请参阅查询分区表

相应架构以内嵌方式指定为 ts:TIMESTAMP,column1:STRING,column2:INTEGER,coumn4:STRING。指定的 TIMESTAMP 字段 ts 用于按小时对数据进行分区。请注意,每小时分区需要 TIMESTAMPDATETIME 列,而不是 DATE 列。

bq mk -t \
--expiration 2592000 \
--schema 'ts:TIMESTAMP,column1:STRING,column2:INTEGER,coumn4:STRING' \
--time_partitioning_field ts \
--time_partitioning_type HOUR \
--time_partitioning_expiration 86400  \
--require_partition_filter \
--description "This is my partitioned table" \
--label org:dev \
mydataset.mypartitionedtable

输入以下命令,在myotherproject(而非默认项目)中创建一个名为 mypartitionedtable 的每日分区表。分区的过期时间设置为 259200 秒(3天),说明设置为 This is my partitioned table,标签设置为 organization:development。该命令使用 -t 快捷方式代替 --table。此命令没有指定表过期时间。如果相关数据集有默认的表过期时间,则系统会应用该过期时间。如果数据集没有默认的表过期时间,则该表将永不过期,但该分区会在 3 天后过期。

相应架构在如下本地 JSON 文件中指定:/tmp/myschema.json。该架构定义包含一个名为 tsTIMESTAMP 字段,用于按天对数据进行分区。

bq mk -t \
--expiration 2592000 \
--schema /tmp/myschema.json \
--time_partitioning_field ts \
--time_partitioning_type DAY \
--time_partitioning_expiration 86400  \
--description "This is my partitioned table" \
--label org:dev \
myotherproject:mydataset.mypartitionedtable

创建表后,您可以使用 bq 命令行工具更新分区表的表过期时间分区过期时间说明标签

API

使用指定了 timePartitioning 属性和 schema 属性的已定义表资源调用 tables.insert 方法。

Go

在尝试此示例之前,请按照《BigQuery 快速入门:使用客户端库》中的 Go 设置说明进行操作。如需了解详情,请参阅 BigQuery Go API 参考文档

import (
	"context"
	"fmt"
	"time"

	"cloud.google.com/go/bigquery"
)

// createTablePartitioned demonstrates creating a table and specifying a time partitioning configuration.
func createTablePartitioned(projectID, datasetID, tableID string) error {
	// projectID := "my-project-id"
	// datasetID := "mydatasetid"
	// tableID := "mytableid"
	ctx := context.Background()

	client, err := bigquery.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("bigquery.NewClient: %v", err)
	}
	defer client.Close()

	sampleSchema := bigquery.Schema{
		{Name: "name", Type: bigquery.StringFieldType},
		{Name: "post_abbr", Type: bigquery.IntegerFieldType},
		{Name: "date", Type: bigquery.DateFieldType},
	}
	metadata := &bigquery.TableMetadata{
		TimePartitioning: &bigquery.TimePartitioning{
			Field:      "date",
			Expiration: 90 * 24 * time.Hour,
		},
		Schema: sampleSchema,
	}
	tableRef := client.Dataset(datasetID).Table(tableID)
	if err := tableRef.Create(ctx, metadata); err != nil {
		return err
	}
	return nil
}

Java

试用此示例之前,请按照《BigQuery 快速入门:使用客户端库》中的 Java 设置说明进行操作。 如需了解详情,请参阅 BigQuery Java API 参考文档

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.Field;
import com.google.cloud.bigquery.Schema;
import com.google.cloud.bigquery.StandardSQLTypeName;
import com.google.cloud.bigquery.StandardTableDefinition;
import com.google.cloud.bigquery.TableId;
import com.google.cloud.bigquery.TableInfo;
import com.google.cloud.bigquery.TimePartitioning;

public class CreatePartitionedTable {

  public static void runCreatePartitionedTable() {
    // TODO(developer): Replace these variables before running the sample.
    String datasetName = "MY_DATASET_NAME";
    String tableName = "MY_TABLE_NAME";
    createPartitionedTable(datasetName, tableName);
  }

  public static void createPartitionedTable(String datasetName, String tableName) {
    try {
      // Initialize client that will be used to send requests. This client only needs to be created
      // once, and can be reused for multiple requests.
      BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();

      TableId tableId = TableId.of(datasetName, tableName);

      TimePartitioning partitioning = TimePartitioning.of(TimePartitioning.Type.DAY);

      Schema schema =
          Schema.of(
              Field.of("stringField", StandardSQLTypeName.STRING),
              Field.of("booleanField", StandardSQLTypeName.BOOL),
              Field.of("dateField", StandardSQLTypeName.DATE));

      StandardTableDefinition tableDefinition =
          StandardTableDefinition.newBuilder()
              .setSchema(schema)
              .setTimePartitioning(partitioning)
              .build();
      TableInfo tableInfo = TableInfo.newBuilder(tableId, tableDefinition).build();

      bigquery.create(tableInfo);
      System.out.println("Partitioned table created successfully");
    } catch (BigQueryException e) {
      System.out.println("Partitioned table was not created. \n" + e.toString());
    }
  }
}

Node.js

在尝试此示例之前,请按照《BigQuery 快速入门:使用客户端库》中的 Node.js 设置说明进行操作。如需了解详情,请查看 BigQuery Node.js API 参考文档

// Import the Google Cloud client library
const {BigQuery} = require('@google-cloud/bigquery');
const bigquery = new BigQuery();

async function createTablePartitioned() {
  // Creates a new partitioned table named "my_table" in "my_dataset".

  /**
   * TODO(developer): Uncomment the following lines before running the sample.
   */
  // const datasetId = "my_dataset";
  // const tableId = "my_table";
  const schema = 'Name:string, Post_Abbr:string, Date:date';

  // For all options, see https://cloud.google.com/bigquery/docs/reference/v2/tables#resource
  const options = {
    schema: schema,
    location: 'US',
    timePartitioning: {
      type: 'DAY',
      expirationMS: '7776000000',
      field: 'date',
    },
  };

  // Create a new table in the dataset
  const [table] = await bigquery
    .dataset(datasetId)
    .createTable(tableId, options);
  console.log(`Table ${table.id} created with partitioning: `);
  console.log(table.metadata.timePartitioning);
}

Python

在尝试此示例之前,请按照《BigQuery 快速入门:使用客户端库》中的 Python 设置说明进行操作。如需了解详情,请参阅 BigQuery Python API 参考文档

# from google.cloud import bigquery
# client = bigquery.Client()
# project = client.project
# dataset_ref = bigquery.DatasetReference(project, 'my_dataset')

table_ref = dataset_ref.table("my_partitioned_table")
schema = [
    bigquery.SchemaField("name", "STRING"),
    bigquery.SchemaField("post_abbr", "STRING"),
    bigquery.SchemaField("date", "DATE"),
]
table = bigquery.Table(table_ref, schema=schema)
table.time_partitioning = bigquery.TimePartitioning(
    type_=bigquery.TimePartitioningType.DAY,
    field="date",  # name of column to use for partitioning
    expiration_ms=7776000000,
)  # 90 days

table = client.create_table(table)

print(
    "Created table {}, partitioned on column {}".format(
        table.table_id, table.time_partitioning.field
    )
)

基于查询结果创建分区表

如需基于查询结果创建分区表,请将结果写入新目标表中。您可以通过查询分区表或非分区表来创建分区表。不能使用查询结果将现有标准表更改为分区表。

基于查询结果创建分区表时,必须使用标准 SQL。目前,无法使用旧版 SQL 查询分区表或将查询结果写入分区表。

通过分区装饰器,您可以将查询结果写入特定分区。例如,如需将结果写入 2016 年 5 月 1 日的分区,请使用以下分区装饰器:

table_name$20160501

使用分区装饰器将查询结果写入特定分区时,被写入分区的数据必须与相应表的分区架构相符。写入分区的所有行的值都应在分区日期范围内。

例如:

以下查询检索自 2018 年 2 月 1 日起的数据,并将数据写入表 mytable$20180201 分区。该表包含两列 - 一个名为 TSTIMESTAMP 列和一个名为 aINT64 列。

bq query \
--nouse_legacy_sql  \
--destination_table=mytable$20180201 \
'SELECT
   TIMESTAMP("2018-02-01") AS TS,
   2 AS a'

以下查询检索自 2018 年 1 月 31 日起的数据,并尝试将数据写入 mytable$20180201 分区。此查询失败,因为您尝试写入的数据不在分区的日期范围内。

bq query \
--nouse_legacy_sql  \
--destination_table=T$20180201 \
'SELECT
   TIMESTAMP("2018-01-31") as TS,
   2 as a'

如需了解如何在分区表中附加或重报(替换)数据,请参阅向分区表附加数据或覆盖其数据。 如需详细了解如何查询分区表,请参阅查询分区表

基于查询结果创建分区表

如需基于查询结果创建分区表,请执行以下操作:

控制台

使用 Cloud Console 查询数据时,您无法为目标表指定分区选项。

bq

输入 bq query 命令,指定 --destination_table 标志可基于查询结果创建一个永久表,指定 --time_partitioning_field 标志可创建分区目标表。

指定 use_legacy_sql=false 标志可使用标准 SQL 语法。要将查询结果写入非默认项目中的某个表,请按以下格式将相应项目 ID 添加到数据集名称:project_id:dataset

(可选)添加 --location 标志并将其值设置为您的位置

输入以下命令可基于查询结果创建一个新的分区目标表:

bq --location=location query \
--destination_table project_id:dataset.table \
--time_partitioning_field column \
--time_partitioning_type unit_time
--use_legacy_sql=false \
'query'

请替换以下内容:

  • location 是位置的名称。--location 是可选标志。例如,如果您在东京地区使用 BigQuery,请将该标志的值设置为 asia-northeast1。您可以使用 .bigqueryrc 文件 设置位置的默认值。
  • project_id 是项目 ID。
  • dataset 是将包含新分区表的数据集的名称。
  • table 是您使用查询结果创建的分区表的名称。
  • column 是用于创建分区的 TIMESTAMPDATE 列的名称。
  • unit_time 可以是 DAYHOURMONTHYEAR,具体取决于所需的时间单位分区粒度。如果未指定 time_partitioning_type,则此变量默认为 DAY
  • query 是使用标准 SQL 语法的查询。不能使用旧版 SQL 查询分区表,也不能将查询结果写入分区表中。

示例:

输入以下命令可将查询结果写入 mydataset 中名为 mypartitionedtable 的目标表。mydataset 属于默认项目。该查询从非分区表(NHTSA 交通事故伤亡公共数据集)中检索数据。该表的 timestamp_of_crash TIMESTAMP 列用于创建分区。

bq query \
--destination_table mydataset.mypartitionedtable \
--time_partitioning_field timestamp_of_crash \
--use_legacy_sql=false \
'SELECT
   state_number,
   state_name,
   day_of_crash,
   month_of_crash,
   year_of_crash,
   latitude,
   longitude,
   manner_of_collision,
   number_of_fatalities,
   timestamp_of_crash
 FROM
   `bigquery-public-data`.nhtsa_traffic_fatalities.accident_2016
 LIMIT
   100'

输入以下命令可将查询结果写入 mydataset 中名为 mypartitionedtable 的目标表。mydataset 属于 myotherproject,而非默认项目。该查询从非分区表(NHTSA 交通事故伤亡公共数据集)中检索数据。该表的 timestamp_of_crash TIMESTAMP 列用于创建分区。

bq query \
--destination_table myotherproject:mydataset.mypartitionedtable \
--time_partitioning_field timestamp_of_crash \
--use_legacy_sql=false \
'SELECT
   state_number,
   state_name,
   day_of_crash,
   month_of_crash,
   year_of_crash,
   latitude,
   longitude,
   manner_of_collision,
   number_of_fatalities,
   timestamp_of_crash
 FROM
   `bigquery-public-data`.nhtsa_traffic_fatalities.accident_2016
 LIMIT
   100'

API

要将查询结果保存到永久分区表中,请调用 jobs.insert 方法,配置一个 query 作业,并为 destinationTabletimePartitioning 属性添加值。

作业资源 jobReference 部分的 location 属性中指定您的位置。

在加载数据时创建分区表

在将数据加载到新表的过程中,可以通过指定分区选项来创建分区表。无需创建空的分区表即可加载数据。可以同时创建分区表和加载数据。

在将数据加载到 BigQuery 中时,可以提供表架构,或者对于支持的数据格式,可以使用架构自动检测功能。

您可以使用分区修饰器将数据加载到特定分区。例如,如需将 2016 年5 月 1 日生成的所有数据加载到 20160501 分区,请使用以下分区装饰器:

table_name$20160501

使用分区装饰器将数据加载到特定分区时,加载到分区的数据必须与相应表的分区架构相符。写入分区的所有行的值都应在分区日期范围内。

如需详细了解如何加载数据,请参阅将数据加载到 BigQuery 简介

将时间单位分区与聚簇操作搭配使用

时间单位分区可以与聚簇操作搭配使用。划分聚簇的时间单位分区表首先按分区列的时间单位(天、小时、月或年)对其数据进行分区,然后在每个分区边界中按聚簇列进一步对数据划分聚簇。

例如,以下命令会创建一个包含每日分区列和聚簇的表。

    bq mk --time_partitioning_type=DAY \
    --time_partitioning_field=ts_column \
    --clustering_fields=column1,column2 \
    mydataset.mytable2 "ts_column:TIMESTAMP,column1:INTEGER,column2:STRING"

检索该表的格式时,您会发现每日时间戳分区和聚簇均已生效:

    bq show --format=prettyjson mydataset.mytable2
    ...
      "clustering": {
        "fields": [
          "column1",
          "column2"
        ]
      },
    ...
      "timePartitioning": {
        "field": "ts_column",
        "type": "DAY"
      },
    ...

如果超过了每个表的分区数限制,或者少量数据分布到多个分区且数据更改过于频繁,请考虑对同一个分区列改用划分聚簇的较大时间间隔分区。这是使用分区来满足分区限制的推荐方法。

例如,以下命令将对同一列创建每日分区和划分聚簇表:

    bq mk --time_partitioning_type=DAY \
    --time_partitioning_field=ts_column \
    --clustering_fields=ts_column,column1 \
    mydataset.mytable2 "ts_column:TIMESTAMP,column1:INTEGER,column2:STRING"

下面是上表的另一个示例,但它具有较长的时间单位分区间隔:

    bq mk --time_partitioning_type=MONTH \
    --time_partitioning_field=ts_column \
    --clustering_fields=ts_column,column1 \
    mydataset.mytable2 "ts_column:TIMESTAMP,column1:INTEGER,column2:STRING"

控制对分区表的访问权限

如需配置对表和视图的访问权限,您可以在以下级层为实体授予 IAM 角色,这些级层按照允许的资源范围从大到小依次排列:

对受 IAM 保护的任何资源的访问权限具有附加性。例如,如果某个实体没有项目等较高级层的访问权限,您可以在数据集级层向该实体授予访问权限,然后该实体便将有权访问该数据集中的表和视图。同样,如果实体没有较高级层或数据集级层的访问权限,您可以在表或视图级层向该实体授予访问权限。

Google Cloud 资源层次结构中授予更高级层(例如项目、文件夹或组织级层)的 IAM 角色,使实体可访问一组广泛的资源。例如,在项目级为实体授予角色会为该实体提供整个项目中所有数据集的访问权限。

在数据集级层授予角色可指定允许实体对该特定数据集中的表和视图执行的操作,即使实体没有更高级层的访问权限也可执行这些操作。如需详细了解如何配置数据集级层的访问权限控制,请参阅控制对数据集的访问权限

在表或视图级层授予角色可指定允许实体对特定表和视图执行的操作,即使实体没有更高级层的访问权限也可执行这些操作。如需了解如何配置表级层的访问权限控制,请参阅控制对表和视图的访问权限

您还可以创建 IAM 自定义角色。如果创建自定义角色,则您授予的权限取决于您希望实体能够执行的具体操作。

您无法对受 IAM 保护的任何资源设置“拒绝”权限。

如需详细了解角色和权限,请参阅:

使用分区表

获取有关分区表的信息

您可以通过以下方式来获取有关表的信息:

  • 使用 Cloud Console。
  • bq 命令行工具中使用 bq show 命令。
  • 调用 tables.get API 方法。
  • 使用客户端库。

所需权限

如需获取有关表的信息,您至少必须获得 bigquery.tables.get 权限。以下预定义的 IAM 角色包含 bigquery.tables.get 权限:

  • bigquery.metadataViewer
  • bigquery.dataViewer
  • bigquery.dataOwner
  • bigquery.dataEditor
  • bigquery.admin

此外,如果用户具有 bigquery.datasets.create 权限,则当该用户创建数据集时,系统会为其授予该数据集的 bigquery.dataOwner 访问权限。借助 bigquery.dataOwner 访问权限,用户可以检索表元数据。

如需详细了解 BigQuery 中的 IAM 角色和权限,请参阅访问权限控制

获取分区表信息

如需查看有关分区表的信息,请执行以下操作:

控制台

  1. 在 Cloud Console 中打开 BigQuery 页面。

    转到 BigQuery 页面

  2. 在导航面板的资源部分中,展开项目和数据集,然后点击列表中的表名称。

  3. 点击查询编辑器下方的详细信息。此标签页会显示表说明和表信息。

    表详细信息

  4. 点击 Schema 标签页查看表的架构定义。请注意,分区表不包含 _PARTITIONTIME 伪列。

bq

发出 bq show 命令可显示所有表信息。使用 --schema 标志可仅显示表的架构信息。可使用 --format 标志来控制输出。

如果您要获取非默认项目中的表信息,请按以下格式将相应项目 ID 添加到数据集:project_id:dataset

bq show --schema --format=prettyjson project_id:dataset.table

请替换以下内容:

  • project_id 是项目 ID。
  • dataset 是数据集的名称。
  • table 是表的名称。

示例:

输入以下命令可显示 mydataset 中有关 mytable 的所有信息。mydataset 属于默认项目。

bq show --format=prettyjson mydataset.mytable

输入以下命令可显示 mydataset 中有关 mytable 的所有信息。mydataset 属于 myotherproject,而非默认项目。

bq show --format=prettyjson myotherproject:mydataset.mytable

输出应如下所示:

{
  "creationTime": "1563236533535",
  "description": "This is my partitioned table",
  "etag": "/ABcDEo7f8GHijKL2mnOpQr==",
  "expirationTime": "1565828533000",
  "id": "myproject:mydataset.mypartitionedtable",
  "kind": "bigquery#table",
  "labels": {
    "org": "dev"
  },
  "lastModifiedTime": "1563236533576",
  "location": "US",
  "numBytes": "0",
  "numLongTermBytes": "0",
  "numRows": "0",
  "requirePartitionFilter": true,
  "schema": {
    "fields": [
      {
        "name": "ts",
        "type": "TIMESTAMP"
      },
      {
        "name": "column1",
        "type": "STRING"
      },
      {
        "name": "column2",
        "type": "INTEGER"
      },
      {
        "name": "column3",
        "type": "STRING"
      }
    ]
  },
  "selfLink": "https://bigquery.googleapis.com/bigquery/v2/projects/myproject/datasets/mydataset/tables/mypartitionedtable",
  "tableReference": {
    "datasetId": "mydataset",
    "projectId": "myproject",
    "tableId": "mypartitionedtable"
  },
  "timePartitioning": {
    "expirationMs": "86400000",
    "field": "ts",
    "requirePartitionFilter": true,
    "type": "DAY"
  },
  "type": "TABLE"
}

输入以下命令可仅显示 mydataset 中有关 mytable 的架构信息。mydataset 属于 myotherproject,而非默认项目。

bq show --schema --format=prettyjson myotherproject:mydataset.mytable

输出应如下所示:

[
  {
    "name": "ts",
    "type": "TIMESTAMP"
  },
  {
    "name": "column1",
    "type": "STRING"
  },
  {
    "name": "column2",
    "type": "INTEGER"
  },
  {
    "name": "column3",
    "type": "STRING"
  }
]

API

调用 bigquery.tables.get 方法并提供所有相关参数。

列出某个数据集内的分区表

您可以通过以下方式列出数据集中的表(包括分区表):

  • 使用 Cloud Console。
  • bq 命令行工具中使用 bq ls 命令。
  • 调用 tables.list API 方法。
  • 使用客户端库。

所需权限

如需列出数据集中的表,您至少必须具有 bigquery.tables.list 权限。以下预定义的 IAM 角色包含 bigquery.tables.list 权限:

  • bigquery.user
  • bigquery.metadataViewer
  • bigquery.dataViewer
  • bigquery.dataEditor
  • bigquery.dataOwner
  • bigquery.admin

如需详细了解 BigQuery 中的 IAM 角色和权限,请参阅访问权限控制

列出分区表

如需列出数据集中的表(包括分区表),请执行以下操作:

控制台

  1. 在 Cloud Console 中打开 BigQuery 页面。

    转到 BigQuery 页面

  2. 在导航面板的资源部分中,展开项目并点击数据集。

  3. 滚动列表,查看数据集中的表。表、分区表、模型和视图由不同的图标进行标识。

bq

发出 bq ls 命令。可使用 --format 标志来控制输出。如果您要列出非默认项目中的表,请按以下格式将相应项目 ID 添加到数据集中:project_id:dataset

bq ls --format=pretty project_id:dataset

请替换以下内容:

  • project_id 是项目 ID。
  • dataset 是数据集的名称。

运行该命令时,Type 字段会显示 TABLEVIEW。对于分区表,Time Partitioning 字段会显示 DAY、用于创建分区的列以及以毫秒为单位的分区到期时间(如果已指定)。

例如:

+-------------------------+-------+----------------------+---------------------------------------------------+
|         tableId         | Type  |        Labels        | Time Partitioning                                 |
+-------------------------+-------+----------------------+---------------------------------------------------+
| mytable                 | TABLE | department:shipping  |  DAY (field: source_date, expirationMs: 86400000) |
| myview                  | VIEW  |                      |                                                   |
+-------------------------+-------+----------------------+---------------------------------------------------+

示例:

输入以下命令可列出默认项目的数据集 mydataset 中的表。

bq ls --format=pretty mydataset

输入以下命令可列出 myotherproject 的数据集 mydataset 中的表。

bq ls --format=pretty myotherproject:mydataset

API

如需使用 API 列出表,请调用 tables.list 方法。

列出分区表中的分区

如需列出分区表中的分区,您可以使用旧版 SQL 查询 __PARTITIONS_SUMMARY__ 元表。

要运行查询,您可以使用 Cloud Console,使用 bq query 命令,也可以调用 jobs.insert 方法并配置 query 作业。

所需权限

如需运行使用 __PARTITIONS_SUMMARY__ 元表的查询作业,您至少必须具有 bigquery.jobs.create 权限。以下预定义的 IAM 角色包含 bigquery.jobs.create 权限:

  • bigquery.user
  • bigquery.jobUser
  • bigquery.admin

您还必须具有 bigquery.tables.getData 权限。以下预定义的 IAM 角色包含 bigquery.tables.getData 权限:

  • bigquery.dataViewer
  • bigquery.dataEditor
  • bigquery.dataOwner
  • bigquery.admin

如需详细了解 BigQuery 中的 IAM 角色,请参阅访问权限控制

列出某个分区表中的分区

您可以使用旧版 SQL 来列出某个分区表中的分区。如需列出分区表中的分区,请按如下所述操作:

控制台

  1. 在 Cloud Console 中打开 BigQuery 页面。

    转到 BigQuery 页面

  2. 点击编写新查询按钮。

  3. 查询编辑器框中输入以下文本,以查询 __PARTITIONS_SUMMARY__ 元表:

    #legacySQL
    SELECT
      partition_id
    FROM
      [dataset.table$__PARTITIONS_SUMMARY__]
    

    请替换以下内容:

    • dataset 是包含表的数据集。
    • table 是表的名称。
  4. 点击运行

bq

使用 bq query 命令输入以下查询:

bq --location=location query \
--use_legacy_sql=true \
'SELECT
  partition_id
FROM
  [dataset.table$__PARTITIONS_SUMMARY__]'

请替换以下内容:

  • location 是位置的名称。--location 是可选标志。例如,如果您在东京地区使用 BigQuery,请将该标志的值设置为 asia-northeast1。您可以使用 ..bigqueryrc 文件设置位置的默认值。
  • dataset 是包含表的数据集。
  • table 是表的名称。

API

调用 jobs.insert 方法,并配置一个用于查询表的 __PARTITIONS_SUMMARY__ 元表的 query 作业。

使用元表获取分区表元数据

您可以通过使用称为元表的特殊表来获取有关分区表的信息:元表包含元数据,例如数据集中的表和视图列表。元表为只读表。

目前,您无法使用 INFORMATION_SCHEMA 服务来获取分区表元数据。

使用元表获取分区元数据

__PARTITIONS_SUMMARY__ 元表是一个特殊的表,其内容表示时间分区表中关于分区的元数据。__PARTITIONS_SUMMARY__ 元表为只读表。

如需访问时间分区表中有关分区的元数据,请在查询的 SELECT 语句中使用 __PARTITIONS_SUMMARY__ 元表。您可以通过以下方式运行查询:

  • 使用 Cloud Console
  • 使用 bq 命令行工具的 bq query 命令
  • 调用 jobs.insert API 方法并配置 query 作业
  • 使用客户端库

目前,标准 SQL 不支持分区修饰器分隔符 ($),因此,您不能使用标准 SQL 来查询 __PARTITIONS_SUMMARY__。使用 __PARTITIONS_SUMMARY__ 元表的旧版 SQL 查询如下所示:

#legacySQL
SELECT
  column
FROM
  [dataset.table$__PARTITIONS_SUMMARY__]

其中:

  • dataset 是您的数据集的名称。
  • table 是时间分区表的名称。
  • column 是以下值之一:
说明
project_id 项目名称。
dataset_id 数据集名称。
table_id 时间分区表的名称。
partition_id 分区的名称(日期)。
creation_time 创建分区的时间,以从 UTC 1970 年 1 月 1 日起计算的毫秒数表示。
last_modified_time 上次修改分区的时间,以从 UTC 1970 年 1 月 1 日起计算的毫秒数表示。

分区元表权限

如需运行使用 __PARTITIONS_SUMMARY__ 元表的查询作业,您至少必须具有 bigquery.jobs.create 权限。以下预定义的 IAM 角色包含 bigquery.jobs.create 权限:

  • bigquery.user
  • bigquery.jobUser
  • bigquery.admin

您还必须具有 bigquery.tables.getData 权限。以下预定义的 IAM 角色包含 bigquery.tables.getData 权限:

  • bigquery.dataViewer
  • bigquery.dataEditor
  • bigquery.dataOwner
  • bigquery.admin

如需详细了解 BigQuery 中的 IAM 角色,请参阅访问权限控制

分区元表示例

以下查询会检索名为 mydataset.mytable 的时间分区表的所有分区元数据。

控制台

#legacySQL
SELECT
  *
FROM
  [mydataset.mytable$__PARTITIONS_SUMMARY__]

bq

bq query --use_legacy_sql=true '
SELECT
  *
FROM
  [mydataset.mytable$__PARTITIONS_SUMMARY__]'

输出如下所示:

+----------------+------------+----------------+--------------+---------------+--------------------+
|   project_id   | dataset_id |    table_id    | partition_id | creation_time | last_modified_time |
+----------------+------------+----------------+--------------+---------------+--------------------+
| myproject      | mydataset  | mytable        | 20160314     | 1517190224120 | 1517190224997      |
| myproject      | mydataset  | mytable        | 20160315     | 1517190224120 | 1517190224997      |
+----------------+------------+----------------+--------------+---------------+--------------------+

以下查询会列出上次修改 mydataset.mytable 中的分区的时间。

控制台

#legacySQL
SELECT
  partition_id,
  last_modified_time
FROM
  [mydataset.mytable$__PARTITIONS_SUMMARY__]

bq

bq query --use_legacy_sql=true '
SELECT
  partition_id,
  last_modified_time
FROM
  [mydataset.mytable$__PARTITIONS_SUMMARY__]'

输出如下所示:

+--------------+--------------------+
| partition_id | last_modified_time |
+--------------+--------------------+
| 20160102     |      1471632556179 |
| 20160101     |      1471632538142 |
| 20160103     |      1471632570463 |
+--------------+--------------------+

为了以便于阅读的格式显示 last_modified_time 字段,请使用 FORMAT_UTC_USEC 函数。例如:

控制台

#legacySQL
SELECT
  partition_id,
  FORMAT_UTC_USEC(last_modified_time*1000) AS last_modified
FROM
  [mydataset.table1$__PARTITIONS_SUMMARY__]

bq

bq query --use_legacy_sql=true '
SELECT
  partition_id,
  FORMAT_UTC_USEC(last_modified_time*1000) AS last_modified
FROM
  [mydataset.mytable$__PARTITIONS_SUMMARY__]'

输出如下所示:

+--------------+----------------------------+
| partition_id |       last_modified        |
+--------------+----------------------------+
| 20160103     | 2016-08-19 18:49:30.463000 |
| 20160102     | 2016-08-19 18:49:16.179000 |
| 20160101     | 2016-08-19 18:48:58.142000 |
+--------------+----------------------------+

后续步骤