

# 创建 Amazon S3 表
<a name="s3-tables-create"></a>

Amazon S3 表是表存储桶的子资源。表以 Apache Iceberg 格式存储，以便您通过使用查询引擎和其它支持 Apache Iceberg 的应用程序来处理这些表。Amazon S3 会持续优化表，以有助于降低存储成本并提高分析查询性能。

创建表时，Amazon S3 会自动为表生成*仓库位置*。仓库位置是一个唯一的 S3 位置，您可以在其中读取和写入与表关联的对象。以下示例显示了仓库位置的格式：

```
s3://63a8e430-6e0b-46f5-k833abtwr6s8tmtsycedn8s4yc3xhuse1b--table-s3
```

表具有以下 Amazon 资源名称（ARN）格式：

```
arn:aws:s3tables:{{region}}:{{owner-account-id}}:bucket/{{bucket-name}}/table/{{table-id}}
```

默认情况下，您可以在表存储桶中创建多达 10000 个表。要请求增加表存储桶或表的配额，请联系 [Amazon Web Services 支持](https://console.amazonaws.cn/support/home#/case/create?issueType=service-limit-increase)。

可以使用 Amazon S3 控制台、Amazon S3 REST API、Amazon SDK、Amazon Command Line Interface（Amazon CLI）或连接到表存储桶的查询引擎来创建表。

创建表时，您可以为该表指定加密设置，除非您使用 Athena 创建表。如果您未指定加密设置，则将使用表存储桶的默认设置对表进行加密。有关更多信息，请参阅 [为表指定加密](s3-tables-kms-specify.md#specify-kms-table)。

**创建表的先决条件**

要创建表，首先必须执行以下操作：
+ [创建表存储桶](s3-tables-buckets-create.md).
+ 在表存储桶中[创建命名空间](s3-tables-namespace-create.md)。
+ 确保您对 `s3tables:CreateTable` 和 `s3tables:PutTableData` 具有 Amazon Identity and Access Management（IAM）权限。
+ 
**注意**  
如果您对表使用 SSE-KMS 加密，则需要对 `s3tables:PutTableEncryption` 拥有权限，并对所选 Amazon KMS 密钥拥有 `DescribeKey` 权限。此外，您使用的 Amazon KMS 密钥需要向 S3 表类数据存储服务授予执行自动表维护的权限。有关更多信息，请参阅 [S3 表类数据存储服务 SSE-KMS 加密的权限要求](s3-tables-kms-permissions.md)。

有关有效表名称的信息，请参阅[表和命名空间的命名规则](s3-tables-buckets-naming.md#naming-rules-table)。

**重要**  
创建表时，请确保在表名称和表定义中全部使用小写字母。例如，请确保列名称全部为小写。如果表名称或表定义包含大写字母，则 Amazon Lake Formation 或 Amazon Glue Data Catalog 不支持该表。在这种情况下，Amazon Athena 等 Amazon 分析服务将无法看到您的表，即使表存储桶与 Amazon 分析服务集成，也不例外。  
如果表定义包含大写字母，则在 Athena 中运行 `SELECT` 查询时会收到以下错误消息：“GENERIC\_INTERNAL\_ERROR: Get table request failed: com.amazonaws.services.glue.model.ValidationException: Unsupported Federation Resource - Invalid table or column names.”

## 使用 S3 控制台和 Amazon Athena
<a name="create-table-console"></a>

以下过程使用 Amazon S3 控制台通过 Amazon Athena 来创建表。如果您尚未在表存储桶中创建命名空间，则可以在此过程中创建命名空间。在执行以下步骤之前，请确保您已在此区域中将表存储桶与 Amazon 分析服务集成。有关更多信息，请参阅 [将 Amazon S3 表类数据存储服务与 Amazon 分析服务集成](s3-tables-integrating-aws.md)。

**注意**  
当您使用 Athena 创建表时，该表将从表存储桶继承默认加密设置。如果要使用不同的加密类型，则需要使用另一种方法创建表。

**创建表**

1. 登录到 Amazon Web Services 管理控制台，然后通过以下网址打开 Amazon S3 控制台：[https://console.aws.amazon.com/s3/](https://console.amazonaws.cn/s3/)。

1. 在左侧导航窗格中，选择**表存储桶**。

1. 在**表存储桶**页面上，选择要在其中创建表的存储桶。

1. 在存储桶详细信息页面上，选择**使用 Athena 创建表**。

1. 在**使用 Athena 创建表**对话框中，执行下列操作之一：
   + 创建新的命名空间。选择**创建命名空间**，然后在**命名空间名称**字段中输入名称。命名空间名称必须为 1 到 255 个字符，并且在表存储桶中是唯一的。有效字符为 a–z、0–9 和下划线 (`_`)。命名空间名称的开头不支持使用下划线。
   + 选择**创建命名空间**。
   + 指定现有的命名空间。选择**指定此表存储桶中的现有命名空间**。然后选择**从现有命名空间中选择**或**输入现有命名空间名称**。如果存储桶中有超过 1000 个命名空间，则当命名空间名称未出现在列表中时，必须输入该名称。

1. 选择**使用 Athena 创建表**。

1. Amazon Athena 控制台将打开，并出现 Athena 查询编辑器。**目录**字段中应填充 **s3tablescatalog/**，后跟表存储桶的名称，例如 **s3tablescatalog/{{amzn-s3-demo-bucket}}**。**数据库**字段中应填充您之前创建或选择的命名空间。
**注意**  
如果您在**目录**和**数据库**字段中看不到这些值，请确保您已在该区域中将表存储桶与 Amazon 分析服务集成。有关更多信息，请参阅 [将 Amazon S3 表类数据存储服务与 Amazon 分析服务集成](s3-tables-integrating-aws.md)。

1. 查询编辑器中填充了一个可用于创建表的示例查询。修改此查询，以指定您希望表具有的表名称和列。

1. 修改完查询后，选择**运行**来创建表。
**注意**  
如果您在尝试在 Athena 中运行查询时收到错误“权限不足，无法执行查询。主体对指定的资源没有任何权限”，则必须向您授予对于表的必需 Lake Formation 权限。有关更多信息，请参阅 [授予对表或数据库的 Lake Formation 权限](grant-permissions-tables.md#grant-lf-table)。
如果您在尝试在 Athena 中运行查询时收到错误“Iceberg 无法访问所请求的资源”，请转到 Amazon Lake Formation 控制台，并确保您已授予自己对您创建的表存储桶目录和数据库（命名空间）的权限。授予这些权限时请勿指定表。有关更多信息，请参阅 [授予对表或数据库的 Lake Formation 权限](grant-permissions-tables.md#grant-lf-table)。
如果在 Athena 中运行 `SELECT` 查询时收到以下错误消息，则此消息是由表名称中或表定义的列名称中具有大写字母而引起的：“GENERIC\_INTERNAL\_ERROR: Get table request failed: com.amazonaws.services.glue.model.ValidationException: Unsupported Federation Resource - Invalid table or column names.” 确保表名称和列名称全部为小写。

如果表创建取得成功，则新表的名称将显示在 Athena 中的表列表中。当您导航回 Amazon S3 控制台时，刷新列表后，新表将出现在表存储桶的存储桶详细信息页面上的**表**列表中。

## 使用 Amazon CLI
<a name="create-table-CLI"></a>

此示例展示了如何使用 Amazon CLI 并使用 JSON 指定表元数据，来通过架构创建表。要使用此示例，请将 `{{user input placeholders}}` 替换为您自己的信息。

```
aws s3tables create-table --cli-input-json file://{{mytabledefinition.json}}
```

对于 `mytabledefinition.json` 文件，请使用以下示例表定义。要使用此示例，请将 `{{user input placeholders}}` 替换为您自己的信息。

```
{
    "tableBucketARN": "arn:aws:s3tables:{{us-east-1}}:{{111122223333}}:bucket/{{amzn-s3-demo-table-bucket}}",
    "namespace": "{{your_namespace}}",
    "name": "{{example_table}}",
    "format": "ICEBERG",
    "metadata": {
        "iceberg": {
            "schema": {
                "fields": [
                     {"name": "{{id}}", "type": "{{int}}",{{"required": true}}},
                     {"name": "{{name}}", "type": "{{string}}"},
                     {"name": "{{value}}", "type": "{{int}}"}
                ]
            }
        }
    }
}
```

## 使用查询引擎
<a name="create-table-engine"></a>

您可以在连接到表存储桶的受支持的查询引擎中创建表，例如在 Amazon EMR 上的 Apache Spark 会话中。

以下示例说明如何通过 Spark 使用 `CREATE` 语句创建表，以及如何使用 `INSERT` 语句或从现有文件中读取数据来添加表数据。要使用此示例，请将 `{{user input placeholders}}` 替换为您自己的信息。

```
spark.sql( 
" CREATE TABLE IF NOT EXISTS s3tablesbucket.{{example_namespace}}.`{{example_table}}` ( 
    id INT, 
    name STRING, 
    value INT 
) 
USING iceberg "
)
```

创建表后，可以将数据加载到表中。从以下方法中进行选择：
+ 使用 `INSERT` 语句向表中添加数据。

  ```
  spark.sql(
  """
      INSERT INTO s3tablesbucket.{{my_namespace}}.{{my_table}} 
      VALUES 
          (1, 'ABC', 100), 
          (2, 'XYZ', 200)
  """)
  ```
+ 加载现有的数据文件。

  1. 将数据读入 Spark：

     ```
     val data_file_location = "{{Path such as S3 URI to data file}}"
     val data_file = spark.read.parquet({{data_file_location}})
     ```

  1. 将数据写入 Iceberg 表：

     ```
     data_file.writeTo("s3tablesbucket.{{my_namespace}}.{{my_table}}").using("Iceberg").tableProperty ("format-version", "2").createOrReplace()
     ```