AWS Athena создает таблицу и раздел - PullRequest
0 голосов
/ 01 декабря 2018

Я сохранил свои данные датчика в S3 (запись данных каждые 5 минут):

farm_iot/sensor_data/farm/farm0001/sensor01/1541252701443

1541252701443 - это файл json, содержащий измерения:

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

Я определенно пропустил некоторый улейумение.К сожалению, я не нашел пример, который извлекает данные json из временных рядов, с которых я начинаю.Я также не уверен, поддерживает ли Hive / Athena этот вид перебора данных.

Я изо всех сил пытаюсь создать таблицу Athena для этих данных ...

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')

Другой путь, которым я являюсьМысль заключается в том, чтобы хранить данные в структуре, которую легче обрабатывать / возможно, я недостаточно разбил данные на части ??!

, поэтому, возможно, мне следует добавить dt к структуре следующим образом:

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 |
+---------------+----------+----------+-------------+--------+

Любой указатель на эту цель был бы очень признателен.Спасибо!

обратите внимание: я не хочу использовать клей и хотел бы понять, как это сделать вручную.кроме клея уже вчера создали ~ 16.000 таблиц :) 10 *

Ответы [ 2 ]

0 голосов
/ 08 декабря 2018

Прежде всего большое спасибо @hlagos за его помощь.

AWS Athena не смогла преобразовать данные датчика json так, как мне это нужно (мы обсуждали это в комментариях к ответу @hlagos).Следовательно, «простейшим» способом решения этой ситуации было изменение формата данных с json на CSV, чтобы он был ближе к нужному мне формату.

Теперь я сохраняю данные датчика в формате S3 в формате CSV (запись данныхкаждые 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 Athena:

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   ...
0 голосов
/ 04 декабря 2018

Позвольте мне попытаться объяснить несколько проблем, которые я вижу впереди.

  • Похоже, что ваш желаемый вывод ожидает некоторые данные, которые являются частью местоположения файла пути, устройства и датчика, однако он не определен как часть вашего определения таблицы, только столбцы в определении таблицы или виртуальные столбцы будут доступны.
  • Несколько небольших файлов могут повлиять на производительность ваших запросов (но это не повлияет на желаемый результат)
  • Разделы Hive используются для повышения производительности запросов, избегая сканирования всех данных.Разделы указывают на папки, в этом случае вы пытаетесь получить доступ к определенным файлам
  • Ваш желаемый вывод в основном разбивает 1 запись в нескольких записях, это не должно обрабатываться при определении таблицы, может быть выполнено через ваш выбороператор
  • Разделы Hive имеют соглашение об именах partitionname=partitionvalue, это не обязательно, но полезно, если вы хотите воспользоваться командами для автоматического добавления разделов на основе структуры папок.

Вот как я бы решил вашу проблему, если вы будете выполнять в основном запросы по датчику или устройству

Измените структуру ваших данных

В идеале структура вашей папки должна исходить из

farm_iot/sensor_data/farm/farm0001/sensor01/1541252701443

на farm_iot / sensor_data / farm / device = farm0001 / sensor = sensor01 / 1541252701443

Измените определение таблицы

Определение таблицы должно содержать расположение разделов набыть в состоянии выбрать его без регулярных выражений и воспользоваться его улучшением производительности (я предполагаю, что общий запрос будет фильтроваться по устройству или датчику. В дополнение к этому вам нужно добавить все ваши столбцы json, которые являются частью вашего файла

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

Если вам нужны давление, температура, влажность и разные ряды, я бы порекомендовал вамЕсли вы сгружаете массив с этими тремя и разбираете его, должно быть намного эффективнее запускать 3 запроса, используя UNION ALL для добавления результатов

Добавление нового раздела

Если вы следуете соглашению Hive, вы можете взятьпреимущество команды 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')

Структура вашей папки будет выглядеть следующим образом:

farm_iot / sensor_data / farm / dt = 20191204 / device = farm0001 / sensor = sensor01 / 1541252701443

Как пояснение, вам не нужно изменять таблицу для каждого нового раздела, только добавляйте эти разделы в таблицу, это то, как Hive будет знать, что создан новый раздел.Если вы решите использовать разделы, это единственный способ, если вы этого не сделаете (это повлияет на производительность), есть другие альтернативы, чтобы заставить его работать

EDIT2:

ЕслиВы хотите сохранить свою структуру данных как есть и не использовать разделы, можно получить ожидаемые результаты следующим образом:

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;

Как видите, я получаю большую часть информации из пути к файлуоднако необходимо установить некоторые флаги, чтобы Hive рекурсивно читал папки

ts,device,sensor,_data_point,value
1541252701443,farm0001,sensor01,temperature,14.78
1541252701443,farm0001,sensor01,pressure,961.7
1541252701443,farm0001,sensor01,humidity,68.32
...