我想知道Athena分区投影如何处理包含具有不同字段的CSV文件的文件夹。假设我的存储桶按年,月和日划分为s3:// SalesPurchases / {year} / {month} / {day}。在每个15分钟的间隔内,我会生成两个文件,描述在该间隔内进行的销售和购买。例如,文件名将为Sales-15min-03:00.csv,表示该文件是在凌晨3点生成的,并具有前15分钟的更新时间。这些文件包含以下字段:
Sales: id, description, amount - (all strings)
Purchases: id, description, vendor, amount - (all strings)
如果我创建用于销售的表:
CREATE EXTERNAL TABLE sales_data (
id string,
description string,
amount string
)
PARTITIONED BY (
`year` string,
`month` string,
`day` string
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
LOCATION 's3://SalesPurchases/'
TBLPROPERTIES (
"skip.header.line.count" = "1",
"projection.enabled" = "true",
"projection.year.type" = "integer",
"projection.year.range" = "2020,2021",
"projection.month.type" = "integer",
"projection.month.range" = "01,12",
"projection.day.type" = "integer",
"projection.day.range" = "01,31",
"storage.location.template" = "s3://SalesPurchases/${year}/${month}/${day}"
)
我只是想知道这种方法的效率。此CREATE语句中没有指示仅过滤“销售”文件。当需要实际查询year = 2020,month = 01,day = 01的数据时,我相信将读取该分区中的所有Sales和Purchase文件。我开始相信这与通过粘合搜寻器创建数据目录条目没有什么不同。它们都将定义相同的架构信息。但是,我确实相信分区投影在某种程度上会更理想。
由于“销售”中的所有字段都是“购买”中字段的子集,所以我也有兴趣了解如何处理此字段。
我注意到的另一个奇怪之处是,当我使用上面的create table语句时,到了查询的时候,我做了类似的事情
select * from sales_data limit 10
select count(*) from sales_data
我得到零结果。我必须在查询中特别添加其他过滤器,以获取有意义的信息,例如
select * from sales_data where year = '2020' and month = '01' and day = '01' limit 10
这与分区投影很奇怪吗?但是,使用搜寻器生成架构信息时并非如此。在这种情况下,select * from sales_data limit 10
将返回非零结果。为什么会这样?
谢谢。
答案 0 :(得分:2)
Athena要求表中的所有文件都具有相同的架构。运行查询时,它将列出并处理表LOCATION
(或表分区的LOCATION
)给定的S3前缀中的所有文件。没有办法告诉它按名称过滤文件,它将始终处理所有文件。无论您是否使用分区投影,此方法都相同。
Glue Crawler也不是解决方案,如果与该设置一起使用,它将完全混乱。
将销售和购买文件放入单独的前缀并创建单独的表。
查询最终结果为零的原因是,您需要将月份和日期分区键配置为零填充:
"projection.month.digits" = "2"
"projection.day.digits" = "2"
令人困惑的是,该范围允许零前缀的值,即使它实际上没有将范围配置为零前缀。