J'ai stocké mes données de capteur dans S3 (écrire des données toutes les 5 minutes):
farm_iot/sensor_data/farm/farm0001/sensor01/1541252701443
1541252701443 est un fichier json contenant les mesures:
{ "temperature": 14.78, "pressure": 961.70, "humidity": 68.32}
Il me manque définitivement des compétences de la ruche. Malheureusement, je n’ai trouvé aucun exemple permettant d’extraire des données JPS de timeseries qui m’a permis de démarrer. Je ne suis pas sûr non plus que météo Hive/Athena prenne en charge ce type de récupération de données.
J'ai du mal à créer une table Athena pour ces données ...
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')
Une autre voie à laquelle je pense est de stocker les données dans une structure plus facile à traiter/peut-être que je n'ai pas assez partitionné les données ??!
alors peut-être que je devrais ajouter dt à la structure comme ceci:
farm_iot/sensor_data/2018-11-03-02-45-02/farm/farm0001/sensor01/1541252701443
ne me fait toujours pas où je veux être:
+---------------+----------+----------+-------------+--------+
| timestamp | device | sensor | data_point | value |
+---------------+----------+----------+-------------+--------+
| 1541252701443 | farm0001 | sensor01 | temperature | 14.78 |
+---------------+----------+----------+-------------+--------+
| 1541252701443 | farm0001 | sensor01 | humidity | 68.32 |
+---------------+----------+----------+-------------+--------+
| 1541252701443 | farm0001 | sensor01 | pressure | 961.70 |
+---------------+----------+----------+-------------+--------+
Tout pointeur vers cet objectif serait très apprécié. Je vous remercie!
remarque: je ne veux pas utiliser de colle et j'aime comprendre comment le faire manuellement. en plus de la colle déjà créée ~ environ 16 000 tables hier :)
Tout d’abord, merci à @hlagos pour son aide.
AWS Athena n'a pas été en mesure de transformer les données du capteur JSON de la manière dont j'en avais besoin (nous en avons discuté dans les commentaires de @hlagos). Par conséquent, le moyen le plus "simple" de gérer cette situation consistait à modifier le format de données de JSON à CSV afin de le rapprocher du format dont j'avais besoin.
Je stocke maintenant les données du capteur au format CSV au format CSV (écriture des données toutes les 5 minutes) et ajoute les partitions de jour et de périphérique dont nous avons parlé.
Structure de dossier résultante:
farm_iot/sensor_data/farm/day=20181129/device=farm0001/1543535738493
le contenu des données du fichier 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
la définition de la table 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');
Les partitions que j'ajoute aiment ceci (plus tard, j'aurai un script pour créer les partitions à l'avance):
msck repair table farm.sensor_data
maintenant je peux interroger les données:
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 ...
Laissez-moi essayer d’expliquer quelques problèmes que je vois au premier plan.
partitionname=partitionvalue
; ceci n'est pas obligatoire, mais utile si vous souhaitez anticiper les commandes pour ajouter automatiquement des partitions en fonction de la structure de vos dossiers. Voici comment résoudre votre problème si vous voulez interroger principalement par capteur ou par appareil
Votre dossier devrait idéalement aller de
farm_iot/sensor_data/farm/farm0001/sensor01/1541252701443
to farm_iot/sensor_data/farm/device = farm0001/sensor = sensor01/1541252701443
Votre définition de table doit contenir les emplacements de vos partitions pour pouvoir la sélectionner sans regex et tirer parti de l'amélioration de ses performances (j'imagine qu'une requête courante va filtrer par périphérique ou par capteur. De plus, vous devez ajouter toutes vos colonnes json. qui font partie de votre dossier
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')
Il nous manque l'horodatage qui fait essentiellement partie de votre nom de fichier avec l'entrée json. Nous pouvons inclure le nom du fichier pendant l'instruction select en utilisant la colonne virtuelle INPUT__FILE__NAME
comme suit
select device, sensor, temperature, preassure, humidity, INPUT__FILE__NAME as mytimestamp from farm.sensor_data
Si vous voulez des valeurs précises, la température et l'humidité, ainsi que différentes lignes, je vous recommande de créer un tableau avec ces trois éléments et de l'exploser, il devrait être très efficace d'exécuter 3 requêtes en utilisant UNION ALL pour ajouter les résultats.
Si vous suivez la convention Hive, vous pouvez utiliser la commande msck repair table pour ajouter automatiquement de nouvelles partitions une fois que de nouveaux périphériques/capteurs sont inclus. Dans le pire des cas, si vous souhaitez conserver la structure de vos dossiers, vous pouvez ajouter des partitions comme suit:
ALTER TABLE test ADD PARTITION (device='farm0001', sensor='sensor01') location 's3://farm_iot/sensor_data/farm/farm0001/sensor01'
NOTE: les nouvelles partitions ne seront pas automatiquement ajoutées, vous devez toujours les ajouter.
J'ai essayé d'ajouter autant de détails que possible. Si quelque chose n'est pas clair, faites le moi savoir.
EDIT: Si vos requêtes seront principalement basées sur des séries chronologiques (plage de dates par exemple), je vous recommanderais d’ajouter une partition au niveau du jour (pas plus petite que celle-ci) pour améliorer les performances de vos requêtes. Donc, votre définition de table ressemblerait à
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')
Et votre structure de dossier ressemblerait à
farm_iot/sensor_data/farm/dt = 20191204/device = farm0001/sensor = sensor01/1541252701443
Pour plus de clarté, il n'est pas nécessaire de modifier la table pour chaque nouvelle partition; vous devez uniquement ajouter ces partitions à la table. C'est essentiellement ainsi que Hive saura qu'une nouvelle partition a été créée. Si vous décidez d’utiliser des partitions, c’est le seul moyen. Si vous n’en avez pas (cela affectera les performances), il existe d’autres alternatives pour que cela fonctionne.
EDIT2:
Si vous souhaitez conserver votre structure de données en l'état et ne pas utiliser de partitions, il est possible d'obtenir les résultats attendus comme suit
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;
Comme vous le voyez, je tire le meilleur parti des informations du chemin du fichier, mais il est nécessaire de définir des indicateurs pour indiquer à Hive les dossiers lus de manière récursive
ts,device,sensor,_data_point,value
1541252701443,farm0001,sensor01,temperature,14.78
1541252701443,farm0001,sensor01,pressure,961.7
1541252701443,farm0001,sensor01,humidity,68.32