雅典娜如何知道如何对数据进行分区?

时间:2019-07-12 22:36:47

标签: amazon-web-services amazon-athena

I've been reading this aws blog article,直到我谈到分区为止,这对我来说都是有意义的。用于创建表的查询如下所示:

, then the code is executable. This is a problem because it doesn't recognize the

这让我感到困惑的是,它的意思是“按年份划分(除其他事项外)”,但是在“ SQL”中没有其他地方指定年份中的数据部分。同样,这些列名称都没有日期类型。那么当您不告诉雅典娜数据的哪一部分是年,月或日时,雅典娜如何知道如何对这些数据进行分区?

在博客文章的上下文中,它说年份来自文件名,但没有任何步骤告诉Athena该信息。文章说这是预定义的格式:https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html#access-log-entry-format,但是我看不到年份列。

编辑:这篇文章不是很明确,但是我认为这可能是说每个CREATE EXTERNAL TABLE IF NOT EXISTS elb_logs_raw_native_part ( request_timestamp string, elb_name string, request_ip string, request_port int, backend_ip string, backend_port int, request_processing_time double, backend_processing_time double, client_response_time double, elb_response_code string, backend_response_code string, received_bytes bigint, sent_bytes bigint, request_verb string, url string, protocol string, user_agent string, ssl_cipher string, ssl_protocol string ) PARTITIONED BY(year string, month string, day string) -- Where does Athena get this data? ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe' WITH SERDEPROPERTIES ( 'serialization.format' = '1','input.regex' = '([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:\-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) \\\"([^ ]*) ([^ ]*) (- |[^ ]*)\\\" (\"[^\"]*\") ([A-Z0-9-]+) ([A-Za-z0-9.-]*)$' ) LOCATION 's3://athena-examples/elb/raw/'; 列都是s3存储桶中的子目录?换句话说,PARTITIONED BY子句中的第一个元素(在本例中为PARTITION BY)是存储桶的第一个子目录,依此类推。

这对我来说仅是部分意义,因为同一篇文章说:“您可以跨多个维度(例如,月,周,日,小时或客户ID)或所有这些维度对数据进行分区。”我不明白,如果它们来自子目录,那么您将如何做所有这些工作,除非您的存储桶中有大量重复项。

2 个答案:

答案 0 :(得分:1)

已链接的

This article比原始版本解释得更好。

  

要创建带有分区的表,必须在CREATE TABLE语句中对其进行定义。使用PARTITIONED BY定义用于对数据进行分区的键。以下各节讨论了两种方案:

     
      
  1. 数据已经分区,存储在Amazon S3上,您需要在Athena上访问数据。

  2.   
  3. 数据未分区。

  4.   

我的问题是关于第一。为此,它说

  

分区存储在Amazon S3中的单独文件夹中。例如,   以下是部分广告展示次数列表:

     

aws s3 ls s3:// elasticmapreduce / samples / hive-ads / tables / impressions /

PRE dt=2009-04-12-13-00/
PRE dt=2009-04-12-13-05/
PRE dt=2009-04-12-13-10/
PRE dt=2009-04-12-13-15/
PRE dt=2009-04-12-13-20/
PRE dt=2009-04-12-14-00/
PRE dt=2009-04-12-14-05/
PRE dt=2009-04-12-14-10/
PRE dt=2009-04-12-14-15/
PRE dt=2009-04-12-14-20/
PRE dt=2009-04-12-15-00/
PRE dt=2009-04-12-15-05/ 
     

此处,日志以列名(dt)设置为等于日期,小时和分钟的增量进行存储。当你   为DDL提供父文件夹,架构和   分区列的名称,Athena可以查询其中的数据   子文件夹。

文章(IMO)的失败之处在于,它从未显示过aws s3 ls。如果可以的话,我不会感到困惑。在本文中,假定有一个称为年,月和日的S3密钥。 PARTITION BY指的是那些键。

如果文件的组织方式不那么整齐,则可以使用其他sql语句读取文件并对其进行分区(上面提到的方案2):

  

ALTER TABLE elb_logs_raw_native_part ADD PARTITION (year='2015',month='01',day='01') location 's3://athena-examples/elb/plaintext/2015/01/01/'

答案 1 :(得分:1)

非常有趣的发现丹尼尔!它使我想起了与AWS支持人员就此主题进行的旧讨论。我想在这里发布摘录,也许有人觉得它有用:

  

我刚刚阅读了有关在S3 [1]中对数据进行分区的Athena文档。
  我想知道“场景1:数据已经以蜂巢格式分区并存储在S3上”,“存储分区数据”中给出的示例:
  命令“ aws s3 ls s3:// elasticmapreduce / samples / hive-ads / tables / impressions /”返回例如“ PRE dt = 2009-04-12-13-00 /”。

     

我的假设是正确的,为了能够在Athena中自动分区数据,我必须在S3文件夹名称前添加“ partition_key = actual_folder_name”?
  否则我不明白为什么上面的示例ls命令返回以“ dt =“前缀开头的S3键。   我认为,此时应在Athena文档中更好地记录“ hive格式的S3上的数据”的含义。 [...]

     

参考文献:
  [1] https://docs.aws.amazon.com/athena/latest/ug/partitions.html

答案

  

我了解您根据AWS文档https://docs.aws.amazon.com/athena/latest/ug/partitions.html

对Athena中的分区存在一些疑问      

回答您的问题:我的假设是正确的,为了能够在Athena中自动分区数据,我必须在S3文件夹名称前加上“ partition_key = actual_folder_name”?

     

是的,您是正确的,为了由Athena自动检测分区,S3前缀应该在'key = value'对中。否则,您必须使用上述文档本身中提到的“更改表..添加分区”命令来手动添加所有这些分区。

     

我知道您发现我们的文档在Hive样式分区方面不那么冗长。 [...]但是,关于Hive分区的描述较少的原因是由于Hive是一种开放源代码工具,有可用的开源文档详细解释了Hive样式分区。例如链接[1],等等。

     

如果由于手动性质而发现更改S3命名或手动添加分区是一项繁琐的任务,那么我建议您使用AWS Glue crawler [2]在您的S3数据上创建Athena表。即使在非Hive样式分区中,Glue也会检测到分区,并将“ Keys”分配给分区,例如“ partition_0”,“ partition_1”等。[...]

     

参考文献:
  [1] http://hadooptutorial.info/partitioning-in-hive/
  [2] https://docs.aws.amazon.com/glue/latest/dg/add-crawler.html