AWS Athena создает таблицу и раздел

Я сохранил данные своего датчика в 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 таблиц :)


person moin moin    schedule 01.12.2018    source источник
comment
вы сталкиваетесь с ошибкой при записи данных или при создании таблицы? пожалуйста, опубликуйте сообщение об ошибке.   -  person Vamsi Prabhala    schedule 02.12.2018
comment
@VamsiPrabhala извините, это не у меня вопрос об ошибке   -  person moin moin    schedule 02.12.2018
comment
только что отредактированный с альтернативой для сохранения данных в текущем формате, однако производительность будет не такой хорошей, как при использовании разделов   -  person hlagos    schedule 05.12.2018
comment
просто добавил сообщение с подробностями о том, что я делаю с этим mark-fink.de/2018-12-09-query-aws-athena-from-jupyter-notebook   -  person moin moin    schedule 09.12.2018


Ответы (2)


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

  • Похоже, что ваш желаемый результат ожидает некоторых данных, которые являются частью местоположения файла пути, устройства и датчика, однако они не определены как часть определения вашей таблицы, а только столбцы в определении таблицы или виртуальные столбцы будут доступны.
  • Несколько небольших файлов могут повлиять на производительность ваших запросов (но это не повлияет на желаемый результат)
  • Разделы Hive используются для повышения производительности запросов, избегая сканирования всех данных. Разделы указывают на папки, в этом случае вы пытаетесь получить доступ к определенным файлам
  • Ваш желаемый результат - это в основном разрушение 1 записи в нескольких записях, это не должно обрабатываться при определении таблицы, может быть выполнено с помощью вашего оператора select
  • Разделы 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. Мы можем включить имя файла во время оператора выбора, используя виртуальный столбец INPUT__FILE__NAME, как показано ниже.

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

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

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

Если вы следуете соглашению Hive, вы можете воспользоваться командой таблица ремонта msck для автоматического добавления новых разделов при добавлении новых устройств / датчиков. В худшем случае, если вы хотите сохранить структуру папок, вы можете добавить разделы следующим образом

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 узнает, что был создан новый раздел. Если вы решите использовать разделы, это единственный способ, если вы этого не сделаете (это повлияет на производительность), есть другие альтернативы, чтобы заставить его работать

РЕДАКТИРОВАТЬ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;

Как видите, я получаю большую часть информации из пути к файлу, однако необходимо установить некоторые флаги, чтобы сообщить 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
person hlagos    schedule 04.12.2018
comment
Спасибо за твой ответ. Мне не очень нравится предложенное вами изменение таблицы, потому что мне придется менять определение таблицы с каждым новым типом датчика, который я представляю. Если я вас правильно понимаю, невозможно разместить данные json в желаемом формате. Это означало бы, что мне лучше хранить данные датчика в формате csv ('устройство', 'датчик', 'точка_данных', 'значение'). Раздел устройства может оказаться полезным. Я не упоминал об этом раньше, но общий запрос будет фильтровать временные ряды по временному срезу, например, день или неделя из данных за два года. - person moin moin; 04.12.2018
comment
если я использую разделы dt и устройства, такие как farm_iot / sensor_data / dt = 2018-11-03-02-45-02 / farm / device = farm0001 / sensor01 / 1541252701443, как работает корреляция между dt и mytimestamp в запросе? Вероятно, это какая-то магия улья, которую я не понимаю (пока). Кстати. означает ли использование разделов, что я должен воссоздавать таблицу перед каждым запросом, чтобы я мог получить последние данные? Чем-то напоминает мне CouchDB несколько лет назад ... - person moin moin; 04.12.2018
comment
Повторное создание таблицы не требуется, вам просто нужно запустить команду msck repair table, чтобы добавить любые новые разделы, в этом случае только если вы добавляете новые папки на уровне устройства или датчика, воссоздание таблицы не требуется. вы должны иметь возможность без проблем загружать полученный json, csv или json не будут иметь никакого значения с этой точки зрения. Что касается вашего предложения о добавлении dt в раздел, это имеет смысл для меня, если это будет общий запрос, однако я бы рекомендовал добавить, что на уровне папки только на дневном уровне вы закончите - person hlagos; 04.12.2018
comment
со слишком большим количеством разделов, что также повлияет на производительность. Позвольте мне обновить свой ответ по этому поводу - person hlagos; 04.12.2018
comment
если я правильно прочитал ваш код, вы вложите в запрос много магии. Я планировал поместить все это в определение таблицы, чтобы запрос был простым (и, надеюсь, производительным). Не уверен, идет ли это в правильном направлении. - person moin moin; 05.12.2018
comment
вы обратили внимание на мои комментарии выше? - person moin moin; 05.12.2018
comment
да, если это так, я бы определенно выбрал вариант раздела, если вы хотите что-то более простое, но, возможно, не тот исполнитель, вы можете выбрать последний вариант и установить вид поверх него. Представление абстрагирует всю магию, совершаемую запросом. - person hlagos; 05.12.2018
comment
просто так нам ясно. Я очень ценю ваш вклад - он очень помог мне обдумать это. Ваши баллы хороши, и ваши ответы верны. Однако это не вопрос из учебника, и я не могу избавиться от мысли, что мы не видели простейшего / оптимального решения проблемы. На выходных я пытаюсь проработать детали того, что я обозначил как подход к решению в моем первом комментарии выше. Если никто не придумает еще лучшего решения, я буду рад наградить вас наградой. - person moin moin; 08.12.2018
comment
вообще без проблем, рад помочь. Я пытался не трогать и не изменять способ хранения данных (у вас не всегда есть контроль). Я рад, что было полезно найти более простое решение - person hlagos; 10.12.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   ...
person moin moin    schedule 08.12.2018