S3にセンサーデータを保存しました(5分ごとにデータを書き込みます)。
farm_iot/sensor_data/farm/farm0001/sensor01/1541252701443
1541252701443は、測定値を含むJSONファイルです。
{ "temperature": 14.78, "pressure": 961.70, "humidity": 68.32}
私は間違いなくいくつかのHiveスキルがありません。残念ながら、私が開始する時系列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テーブルをすでに作成しました:)
何よりもまず、@ hlagosの支援に感謝します。
AWS Athenaは、jsonセンサーデータを必要な方法で変換できませんでした(@hlagos answerへのコメントでこれを説明しました)。その結果、その状況に対処する「最も簡単な」方法は、データ形式を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 ...
正面にあるいくつかの問題について説明してみましょう。
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ステートメント中にファイル名を含めることができます
select device, sensor, temperature, preassure, humidity, INPUT__FILE__NAME as mytimestamp from farm.sensor_data
事前保証、温度、湿度、異なる行が必要な場合は、これら3つの配列を作成して展開することをお勧めします。UNIONALLを使用して3つのクエリを実行し、結果を追加するのが非常に効率的です。
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