使用动态 ID 分区 - Amazon Athena

使用动态 ID 分区

当数据按高基数属性分区时,或者无法事先知道这些值时,您可以使用 injected 投影类型。此类属性的示例包括用户名以及设备或产品的 ID。当您使用 injected 投影类型配置分区键时,Athena 使用查询本身的值来计算要读取的分区集。

如果某个表具有通过 injected 投影类型配置的分区键,则要使 Athena 能够在该表上运行查询,必须满足以下条件:

  • 查询必须包括至少一个分区键值。

  • 值必须是无需读取任何数据即可评估的文字或表达式。

只要其中一个条件不满足,查询就会失败,并显示以下错误:

CONSTRAINT_VIOLATION:对于注入的投影分区列 column_name,WHERE 子句必须仅包含静态相等条件,并且必须至少存在一个此类条件。

何时使用 injected 投影类型

设想您的数据集包含来自 IoT 设备的事件,并按设备的 ID 进行分区。该数据集具有以下特征:

  • 设备 ID 随机生成。

  • 新设备经常预置。

  • 目前有数十万台设备,将来会有数百万台。

使用传统的元数据存储很难管理此数据集。难以确保数据存储与元存储之间保持分区同步,而且在查询规划期间筛选分区可能很慢。但是,如果您将表配置为使用分区投影并使用 injected 投影类型,您会获得两个优势:您不必在元存储中管理分区,并且您的查询不必查找分区元数据。

以下 CREATE TABLE 示例会为刚刚描述的设备事件数据集创建一个表。该表使用注入投影类型。

CREATE EXTERNAL TABLE device_events ( event_time TIMESTAMP, data STRING, battery_level INT ) PARTITIONED BY ( device_id STRING ) LOCATION "s3://amzn-s3-demo-bucket/prefix/" TBLPROPERTIES ( "projection.enabled" = "true", "projection.device_id.type" = "injected", "storage.location.template" = "s3://amzn-s3-demo-bucket/prefix/${device_id}" )

以下示例查询会查找在 12 小时内从三台特定设备收到的事件数。

SELECT device_id, COUNT(*) AS events FROM device_events WHERE device_id IN ( '4a770164-0392-4a41-8565-40ed8cec737e', 'f71d12cf-f01f-4877-875d-128c23cbde17', '763421d8-b005-47c3-ba32-cc747ab32f9a' ) AND event_time BETWEEN TIMESTAMP '2023-11-01 20:00' AND TIMESTAMP '2023-11-02 08:00' GROUP BY device_id

当您运行此查询时,Athena 会看到 device_id 分区键的三个值,并使用这些值来计算分区位置。Athena 使用 storage.location.template 属性的值来生成以下位置:

  • s3://amzn-s3-demo-bucket/prefix/4a770164-0392-4a41-8565-40ed8cec737e

  • s3://amzn-s3-demo-bucket/prefix/f71d12cf-f01f-4877-875d-128c23cbde17

  • s3://amzn-s3-demo-bucket/prefix/763421d8-b005-47c3-ba32-cc747ab32f9a

如果您在分区投影配置中省略了 storage.location.template 属性,Athena 会使用 Hive 风格分区,根据 LOCATION 中的值(例如,s3://amzn-s3-demo-bucket/prefix/device_id=4a770164-0392-4a41-8565-40ed8cec737e)投影分区位置。