waq*_*ner 0 amazon-s3 amazon-athena aws-glue
我有一个带有约7000万JSON(〜15TB)的S3存储桶,以及一个可以通过时间戳和JSON中定义的其他键查询的雅典娜表。
可以保证JSON中的时间戳或多或少等于JSON的S3createdDate(或者至少等于我的查询目的)
我可以通过将createddate添加为“ partition”之类的方式来以某种方式提高查询性能(和成本)吗?我不理解,似乎只能使用前缀/文件夹吗?
编辑:目前,我通过使用S3广告资源CSV通过createdDate进行预过滤,然后下载所有JSON并进行其余过滤,来进行模拟,但我想尽可能在athena内完成此操作
无法使Athena使用诸如S3对象元数据之类的东西进行查询计划。使Athena跳过读取对象的唯一方法是组织对象,以便可以建立分区表,然后使用分区键上的过滤器进行查询。
听起来您对Athena中的分区如何工作有一个想法,我认为您没有使用它是有原因的。但是,为了使其他遇到类似问题的人受益,我将首先说明如果可以更改对象的组织方式可以做什么。最后,我会提出其他建议,您可能想直接跳到那。
我建议您使用包含对象时间戳记一部分的前缀来组织JSON对象。究竟多少取决于查询数据的方式。您不希望它过于细小和粗糙。使其过于精细将使Athena花更多时间在S3上列出文件,使其过于粗糙将使其读取太多文件。如果查询的最常见时间段是一个月,那是一个很好的粒度;如果最常见的时间段是几天,则一天可能会更好。
例如,如果day是数据集的最佳粒度,则可以使用如下键来组织对象:
s3://some-bucket/data/2019-03-07/object0.json
s3://some-bucket/data/2019-03-07/object1.json
s3://some-bucket/data/2019-03-08/object0.json
s3://some-bucket/data/2019-03-08/object1.json
s3://some-bucket/data/2019-03-08/object2.json
Run Code Online (Sandbox Code Playgroud)
您还可以使用Hive样式的分区方案,这是诸如Glue,Spark和Hive之类的其他工具所期望的,因此,除非您有理由不这样做,否则将来可以避免您的痛苦:
s3://some-bucket/data/created_date=2019-03-07/object0.json
s3://some-bucket/data/created_date=2019-03-07/object1.json
s3://some-bucket/data/created_date=2019-03-08/object0.json
Run Code Online (Sandbox Code Playgroud)
我在created_date这里选择的名称,我不知道您的数据将是一个好名字。您可以使用just date,但请记住始终将其引用(并在DML和DDL中以不同的方式引用…),因为它是保留字。
然后创建一个分区表:
CREATE TABLE my_data (
column0 string,
column1 int
)
PARTITIONED BY (created_date date)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION 's3://some-bucket/data/'
TBLPROPERTIES ('has_encrypted_data'='false')
Run Code Online (Sandbox Code Playgroud)
然后,一些指南将告诉您运行MSCK REPAIR TABLE以加载表的分区。如果您使用Hive样式的分区(即…/created_date=2019-03-08/…),则可以执行此操作,但是这会花费很长时间,因此我不建议这样做。通过手动添加分区,您可以做得更好:
ALTER TABLE my_data
ADD PARTITION (created_date = '2019-03-07') LOCATION 's3://some-bucket/data/created_date=2019-03-07/'
ADD PARTITION (created_date = '2019-03-08') LOCATION 's3://some-bucket/data/created_date=2019-03-08/'
Run Code Online (Sandbox Code Playgroud)
最后,当您查询表时,请确保包括该created_date列以向Athena提供信息,以使其仅读取与查询相关的对象:
SELECT COUNT(*)
FROM my_data
WHERE created_date >= DATE '2019-03-07'
Run Code Online (Sandbox Code Playgroud)
您可以验证该查询将通过观察数据的差异便宜扫描时,例如从改变created_date >= DATE '2019-03-07'到created_date = DATE '2019-03-07'。
如果您无法更改对象在S3上的组织方式,则存在文档记录不完善的功能,即使您无法更改数据对象,也可以创建分区表。您要做的是创建与我上面建议的相同的前缀,但是您无需将JSON对象移动到此结构中,而是symlink.txt在每个分区的前缀中放置一个名为的文件:
s3://some-bucket/data/created_date=2019-03-07/symlink.txt
s3://some-bucket/data/created_date=2019-03-08/symlink.txt
Run Code Online (Sandbox Code Playgroud)
在每个symlink.txt分区中,放入要包含在该分区中的文件的完整S3 URI。例如,在第一个文件中,您可以输入:
s3://data-bucket/data/object0.json
s3://data-bucket/data/object1.json
Run Code Online (Sandbox Code Playgroud)
第二个文件:
s3://data-bucket/data/object2.json
s3://data-bucket/data/object3.json
s3://data-bucket/data/object4.json
Run Code Online (Sandbox Code Playgroud)
然后,您创建一个表,该表看起来与上面的表非常相似,但有一点点不同:
CREATE TABLE my_data (
column0 string,
column1 int
)
PARTITIONED BY (created_date date)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
STORED AS INPUTFORMAT 'org.apache.hadoop.hive.ql.io.SymlinkTextInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION 's3://some-bucket/data/'
TBLPROPERTIES ('has_encrypted_data'='false')
Run Code Online (Sandbox Code Playgroud)
注意该INPUTFORMAT属性的值。
您可以像添加任何分区表一样添加分区:
ALTER TABLE my_data
ADD PARTITION (created_date = '2019-03-07') LOCATION 's3://some-bucket/data/created_date=2019-03-07/'
ADD PARTITION (created_date = '2019-03-08') LOCATION 's3://some-bucket/data/created_date=2019-03-08/'
Run Code Online (Sandbox Code Playgroud)
我为此遇到的唯一与Athena相关的文档是用于与Athena集成的S3库存文档。
我开始使用 Theo 的答案,它非常接近(谢谢 Theo 出色且非常详细的回复),但是根据文档添加多个分区时,您只需要在查询开头附近指定一次“ADD”。
我尝试在每个 Theo 示例的每一行上指定“ADD”,但收到错误。不过,仅指定一次时它就有效。以下是我成功使用的格式:
ALTER TABLE db.table_name ADD IF NOT EXISTS
PARTITION (event_date = '2019-03-01') LOCATION 's3://bucket-name/2019-03-01/'
PARTITION (event_date = '2019-03-02') LOCATION 's3://bucket-name/2019-03-02/'
PARTITION (event_date = '2019-03-03') LOCATION 's3://bucket-name/2019-03-03/'
...
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1815 次 |
| 最近记录: |