使用动态 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