代码之家  ›  专栏  ›  技术社区  ›  moin moin

AWS Athena创建表和分区

  •  7
  • moin moin  · 技术社区  · 7 年前

    我将传感器数据存储在S3中(每5分钟写入一次数据):

    farm_iot/sensor_data/farm/farm0001/sensor01/1541252701443
    

    1541252701443是一个json文件,其中包含测量值:

    {  "temperature": 14.78,  "pressure": 961.70,  "humidity": 68.32}
    

    我肯定缺少一些蜂巢技能。不幸的是,我没有找到一个能够提取timeseries json数据的示例。我也不确定蜂巢/雅典娜是否支持这种数据争夺。

    CREATE EXTERNAL TABLE IF NOT EXISTS farm.sensor_data (
      device string,
      sensor string,
      data_point string,
      value double
    )
    ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
    WITH SERDEPROPERTIES (
      'serialization.format' = '1'
    ) LOCATION 's3://farm-iot/sensor_data/farm/farm0001/sensor01/'
    PARTITIONED BY (timestamp string)
    TBLPROPERTIES ('has_encrypted_data'='false')
    

    我想的另一种方法是将数据存储在一个更容易处理的结构中/也许我没有对数据进行足够的分区??!

    所以也许我应该补充一点 对于这样的结构:

    farm_iot/sensor_data/2018-11-03-02-45-02/farm/farm0001/sensor01/1541252701443
    

    +---------------+----------+----------+-------------+--------+
    | timestamp     | device   | sensor   | data_point  | value  |
    +---------------+----------+----------+-------------+--------+
    | 1541252701443 | farm0001 | sensor01 | temperature |  14.78 |
    +---------------+----------+----------+-------------+--------+
    | 1541252701443 | farm0001 | sensor01 | humidity    |  68.32 |
    +---------------+----------+----------+-------------+--------+
    | 1541252701443 | farm0001 | sensor01 | pressure    | 961.70 |
    +---------------+----------+----------+-------------+--------+
    

    任何指向这一目标的指针都将不胜感激。非常感谢。

    请注意:我不想使用胶水,我想了解如何手动操作。此外,glue昨天已经创建了约16000个表:)

    2 回复  |  直到 7 年前
        1
  •  9
  •   hlagos    7 年前

    • 看起来您所需的输出需要一些数据,这些数据是路径文件位置、设备和传感器的一部分,但是它没有定义为表定义的一部分,只有表定义或传感器中的列 virtual columns 将提供。
    • 几个小文件可能会影响查询的性能(但这不会影响所需的结果)
    • 所有的数据。分区指向文件夹,在这种情况下,您试图访问特定的文件
    • 您想要的输出基本上是将一条记录分解成多条记录,这不应该在表定义中处理,可以通过select语句来完成
    • 配置单元分区的命名约定为 partitionname=partitionvalue ,这不是强制性的,但如果您希望提前使用命令根据文件夹结构自动添加分区,则此选项非常有用。

    如果您主要通过传感器或设备进行查询,我会这样解决您的问题

    farm_iot/sensor_data/farm/farm0001/sensor01/1541252701443
    

    至农场物联网/传感器数据/农场/设备=农场0001/传感器=传感器01/1541252701443

    CREATE EXTERNAL TABLE IF NOT EXISTS farm.sensor_data (
      temperature double,
      preassure double,
      humidity double
    )
    ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
    WITH SERDEPROPERTIES (
      'serialization.format' = '1'
    ) LOCATION 's3://farm-iot/sensor_data/farm/'
    PARTITIONED BY (device string, sensor string)
    TBLPROPERTIES ('has_encrypted_data'='false')
    

    查询您的数据

    我们缺少时间戳,它本质上是json输入文件名的一部分。我们可以在select语句中使用虚拟列包含文件名 INPUT__FILE__NAME 如下

    select device, sensor, temperature, preassure, humidity, INPUT__FILE__NAME as mytimestamp from farm.sensor_data
    

    如果您需要预压力、温度和湿度以及不同的行,我建议您使用这三个行创建一个数组并将其分解,使用UNION ALL运行3个查询以附加结果应该会非常有效

    如果遵循配置单元约定,则可以利用该命令 msck repair table

    ALTER TABLE test ADD PARTITION (device='farm0001', sensor='sensor01') location 's3://farm_iot/sensor_data/farm/farm0001/sensor01'
    

    我试图尽可能多地增加细节。如果有不清楚的地方,请告诉我。

    编辑: 如果您的查询主要基于时间序列(例如日期范围),我建议在日级别添加一个分区(不小于此分区),以提高查询的性能。因此,您的表定义如下所示

    CREATE EXTERNAL TABLE IF NOT EXISTS farm.sensor_data (
      temperature double,
      preassure double,
      humidity double
    )
    ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
    WITH SERDEPROPERTIES (
      'serialization.format' = '1'
    ) LOCATION 's3://farm-iot/sensor_data/farm/'
    PARTITIONED BY (dt=long, device string, sensor string)
    TBLPROPERTIES ('has_encrypted_data'='false')
    

    农场物联网/传感器数据/农场/dt=20191204/设备=farm0001/传感器=sensor01/1541252701443

    作为说明,您不需要为每个新分区修改表,只需将这些分区添加到表中,这基本上就是Hive知道新分区已创建的方式。如果您决定使用分区,这是唯一的方法,如果您不这样做(这将影响性能),那么还有其他一些方法可以让它工作

    编辑2:

    如果您希望保持数据结构不变,并且不使用分区,那么可以得到如下预期结果

    CREATE EXTERNAL TABLE IF NOT EXISTS yourdb.sensordata (
      temperature double,
      pressure double,
      humidity double
    )
    ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
    WITH SERDEPROPERTIES (
      'serialization.format' = '1'
    ) 
    LOCATION 's3://farm-iot/sensor_data/farm/'
    TBLPROPERTIES ('has_encrypted_data'='false');
    
    SET hive.mapred.supports.subdirectories=TRUE;
    SET mapred.input.dir.recursive=TRUE;
    select * from yourdb.sensordata;
    
    select 
    split(input__file__name, "/")[size(split(input__file__name, "/")) - 1] as ts,
    split(input__file__name, "/")[size(split(input__file__name, "/")) - 3] as device,
    split(input__file__name, "/")[size(split(input__file__name, "/")) - 2] as sensor,
    'temperature' as data_point,
    temperature as value
    from yourdb.sensordata
    union all
    select 
    split(input__file__name, "/")[size(split(input__file__name, "/")) - 1] as ts,
    split(input__file__name, "/")[size(split(input__file__name, "/")) - 3] as device,
    split(input__file__name, "/")[size(split(input__file__name, "/")) - 2] as sensor,
    'pressure' as data_point,
    pressure as value
    from yourdb.sensordata
    union all
    select 
    split(input__file__name, "/")[size(split(input__file__name, "/")) - 1] as ts,
    split(input__file__name, "/")[size(split(input__file__name, "/")) - 3] as device,
    split(input__file__name, "/")[size(split(input__file__name, "/")) - 2] as sensor,
    'humidity' as data_point,
    humidity as value
    from yourdb.sensordata;
    

    ts,device,sensor,_data_point,value
    1541252701443,farm0001,sensor01,temperature,14.78
    1541252701443,farm0001,sensor01,pressure,961.7
    1541252701443,farm0001,sensor01,humidity,68.32
    
        2
  •  5
  •   moin moin    7 年前

    首先,非常感谢@hlagos的帮助。

    AWS Athena无法以我需要的方式转换json传感器数据(我们在@hlagos answer的评论中讨论了这一点)。因此,处理这种情况的“最简单”方法是将数据格式从json更改为CSV,以更接近我需要的格式。

    现在,我将传感器数据以CSV格式存储在S3中(每5分钟写入一次数据),并添加了我们讨论的日期和设备分区。

    生成的文件夹结构:

    farm_iot/sensor_data/farm/day=20181129/device=farm0001/1543535738493
    

    CSV文件的数据内容:

    sensor01,temperature,2.82
    sensor01,pressure,952.83
    sensor01,humidity,83.64
    sensor02,temperature,2.61
    sensor02,pressure,952.74
    sensor02,humidity,82.41
    

    AWS雅典娜表格定义:

    CREATE EXTERNAL TABLE IF NOT EXISTS farm.sensor_data (
      `sensor` string,
      `data_point` string,
      `value` double 
    ) 
    PARTITIONED BY (day string, device string)
    ROW FORMAT DELIMITED
        FIELDS TERMINATED BY ','
        ESCAPED BY '\\'
        LINES TERMINATED BY '\n'
    LOCATION 's3://farm-iot/sensor_data/farm/'
    TBLPROPERTIES ('has_encrypted_data'='false');
    

    我添加的分区如下(稍后我将有一个脚本来提前创建分区):

    msck repair table farm.sensor_data
    

    现在我可以查询数据了:

    select regexp_extract("$path", '[^/]+$') as timestamp, device, sensor, 
        data_point, value from farm.sensor_data where day='20181104'
    
    Results
        timestamp       device      sensor      data_point  value
    1   1541310040278   farm0001    sensor01    temperature 21.61
    2   1541310040278   farm0001    sensor01    pressure    643.65
    3   1541310040278   farm0001    sensor01    humidity    74.84
    4   1541310040278   farm0001    sensor02    temperature 9.14
    5   1541310040278   farm0001    sensor02    pressure    956.04
    6   1541310040278   farm0001    sensor02    humidity    88.01
    7   1541311840309   farm0001    sensor01    temperature 21.61
    8   ...