Elaborare e analizzare documenti JSON usando Hive in HDInsight

Informazioni su come elaborare e analizzare file JSON usando Hive in HDInsight. Nell'esercitazione viene usato il documento JSON seguente:

{
    "StudentId": "trgfg-5454-fdfdg-4346",
    "Grade": 7,
    "StudentDetails": [
        {
            "FirstName": "Peggy",
            "LastName": "Williams",
            "YearJoined": 2012
        }
    ],
    "StudentClassCollection": [
        {
            "ClassId": "89084343",
            "ClassParticipation": "Satisfied",
            "ClassParticipationRank": "High",
            "Score": 93,
            "PerformedActivity": false
        },
        {
            "ClassId": "78547522",
            "ClassParticipation": "NotSatisfied",
            "ClassParticipationRank": "None",
            "Score": 74,
            "PerformedActivity": false
        },
        {
            "ClassId": "78675563",
            "ClassParticipation": "Satisfied",
            "ClassParticipationRank": "Low",
            "Score": 83,
            "PerformedActivity": true
        }
    ]
}

Il file è disponibile in wasb://processjson@hditutorialdata.blob.core.windows.net/. Per altre informazioni sull'uso dell'archivio BLOB di Azure con HDInsight, vedere Usare un archivio BLOB di Azure compatibile con HDFS con Hadoop in HDInsight. È possibile copiare il file nel contenitore predefinito del cluster.

In questa esercitazione viene usata la console di Hive. Per istruzioni sull'apertura della console Hive, vedere Usare Hive con Hadoop in HDInsight con Desktop remoto.

Rendere flat i documenti JSON

I metodi elencati nella sezione seguente presuppongono che il documento JSON sia in una singola riga. È quindi necessario rendere flat il documento JSON in una stringa. Se il documento JSON è già flat, è possibile saltare questo passaggio e passare alla sezione successiva relativa all'analisi dei dati JSON.

DROP TABLE IF EXISTS StudentsRaw;
CREATE EXTERNAL TABLE StudentsRaw (textcol string) STORED AS TEXTFILE LOCATION "wasb://processjson@hditutorialdata.blob.core.windows.net/";

DROP TABLE IF EXISTS StudentsOneLine;
CREATE EXTERNAL TABLE StudentsOneLine
(
  json_body string
)
STORED AS TEXTFILE LOCATION '/json/students';

INSERT OVERWRITE TABLE StudentsOneLine
SELECT CONCAT_WS(' ',COLLECT_LIST(textcol)) AS singlelineJSON
      FROM (SELECT INPUT__FILE__NAME,BLOCK__OFFSET__INSIDE__FILE, textcol FROM StudentsRaw DISTRIBUTE BY INPUT__FILE__NAME SORT BY BLOCK__OFFSET__INSIDE__FILE) x
      GROUP BY INPUT__FILE__NAME;

SELECT * FROM StudentsOneLine

Il file JSON non elaborato è disponibile in wasb://processjson@hditutorialdata.blob.core.windows.net/. La tabella Hive StudentsRaw punta al documento JSON non elaborato e non flat.

La tabella Hive StudentsOneLine archivia i dati nel file system predefinito di HDInsight nel percorso /json/students/.

L'istruzione INSERT popola la tabella StudentOneLine con i dati JSON flat.

L'istruzione SELECT restituirà solo una riga.

Ecco l'output dell'istruzione SELECT:

Rendere flat il documento JSON.

Analizzare i documenti JSON in Hive

Hive offre tre meccanismi diversi per l'esecuzione di query nei documenti JSON:

  • Usare la funzione definita dall'utente GET_JSON_OBJECT UDF.
  • Usare la funzione definita dall'utente JSON_TUPLE.
  • Usare l'interfaccia SerDe personalizzata.
  • Scrivere una funzione definita dall'utente personalizzata usando Python o altri linguaggi. Vedere questo articolo sull'esecuzione del codice Python personalizzato con Hive.

Usare la funzione definita dall'utente GET_JSON_OBJECT

Hive offre una funzione definita dall'utente predefinita denominata get json object in grado di eseguire query JSON in fase di esecuzione. Questo metodo accetta due argomenti, ovvero il nome della tabella e il nome del metodo che include il documento JSON flat e il campo JSON da analizzare. L'esempio seguente illustra il funzionamento di questa funzione definita dall'utente.

Ottenere il nome e il cognome di ogni studente

SELECT
  GET_JSON_OBJECT(StudentsOneLine.json_body,'$.StudentDetails.FirstName'),
  GET_JSON_OBJECT(StudentsOneLine.json_body,'$.StudentDetails.LastName')
FROM StudentsOneLine;

Questo è l'output ottenuto quando si esegue la query nella finestra della console.

Funzione definita dall'utente get_json_object

La funzione definita dall'utente get-json_object presenta alcune limitazioni.

  • Poiché ogni campo della query richiede una nuova analisi della query, si ha un impatto sulle prestazioni.
  • GET_JSON_OBJECT() restituisce la rappresentazione di stringa di una matrice. Per convertirla in una matrice Hive, è necessario usare espressioni regolari per sostituire le parentesi quadre ('[' e ']') e quindi chiamare anche una suddivisione per ottenere la matrice.

Il wiki relativo a Hive consiglia quindi di usare json_tuple, come illustrato più avanti.

Usare la funzione definita dall'utente JSON_TUPLE

L'altra funzione definita dall'utente disponibile in Hive è denominata json_tuple e offre prestazioni migliori rispetto a get_ json _object. Questo metodo accetta un insieme di chiavi e una stringa JSON e restituisce una tupla di valori usando una funzione. La query seguente restituisce l'ID dello studente e il livello dal documento JSON:

SELECT q1.StudentId, q1.Grade
  FROM StudentsOneLine jt
  LATERAL VIEW JSON_TUPLE(jt.json_body, 'StudentId', 'Grade') q1
    AS StudentId, Grade;

Output dello script nella console di Hive:

Funzione definita dall'utente json_tuple

JSON_TUPLE usa la sintassi di tipo lateral view in Hive, che consente a json_tuple di creare una tabella virtuale applicando la funzione UDT a ogni riga della tabella originale. I documenti JSON complessi diventano troppo difficili da gestire a causa dell'uso ripetuto di LATERAL VIEW. JSON_TUPLE non è in grado di gestire documenti JSON annidati.

Usare l'interfaccia SerDe personalizzata

SerDe è la scelta migliore per l'analisi di documenti JSON annidati, perché consente di definire lo schema JSON e di usarlo per analizzare i documenti. In questa esercitazione viene usata una delle interfacce SerDe più diffuse, sviluppata da rcongiu.

Per usare l'interfaccia SerDe personalizzata:

  1. Installare Java SE Development Kit 7u55 JDK 1.7.0_55. Se si usa la distribuzione Windows di HDInsight, scegliere la versione Windows X64 del JDK.

    Avviso

    JDK 1.8 non funziona con questa SerDe.

    Al termine dell'installazione, aggiungere una nuova variabile di ambiente utente:

    1. Aprire Visualizza impostazioni di sistema avanzate dalla schermata di Windows.
    2. Fare clic su Variabili di ambiente.
    3. Aggiungere una nuova variabile di ambiente JAVA_HOME che punta a C:\Programmi\Java\jdk1.7.0_55 o al percorso di installazione del JDK.

      Configurazione dei valori di configurazione corretti per JDK

  2. Installare Maven 3.3.1

    Aggiungere la cartella Bin al percorso scegliendo Pannello di controllo-->Modifica le variabili di ambiente relative al sistema per l'account, quindi scegliere Variabili di ambiente. La schermata seguente illustra come eseguire questa operazione.

    Configurazione di Maven

  3. Clonare il progetto dal sito GitHub Hive-JSON-SerDe . Per eseguire questa operazione, fare clic sul pulsante "Download Zip", come illustrato nella schermata seguente.

    Clonazione del progetto

4: Passare alla cartella in cui è stato scaricato il pacchetto e quindi digitare "mvn package". Verranno creati i file jar necessari, che verranno quindi copiati nel cluster.

5: Passare alla cartella di destinazione nella cartella radice in cui è stato scaricato il pacchetto. Caricare il file json-serde-1.1.9.9-Hive13-jar-with-dependencies.jar nel nodo head del cluster. È in genere consigliabile inserirlo sotto la cartella dei file binari di Hive, ad esempio C:\apps\dist\hive-0.13.0.2.1.11.0-2316\bin o in una cartella analoga.

6: Al prompt di Hive digitare "add jar /path/to/json-serde-1.1.9.9-Hive13-jar-with-dependencies.jar". Poiché in questo esempio il file jar si trova nella cartella C:\apps\dist\hive-0.13.x\bin, è possibile aggiungere direttamente il file jar con il nome, come illustrato di seguito:

add jar json-serde-1.1.9.9-Hive13-jar-with-dependencies.jar;

Aggiunta di JAR al progetto

A questo punto è possibile usare SerDe per eseguire le query sul documento JSON.

L'istruzione seguente crea una tabella con uno schema definito:

DROP TABLE json_table;
CREATE EXTERNAL TABLE json_table (
  StudentId string,
  Grade int,
  StudentDetails array<struct<
      FirstName:string,
      LastName:string,
      YearJoined:int
      >
  >,
  StudentClassCollection array<struct<
      ClassId:string,
      ClassParticipation:string,
      ClassParticipationRank:string,
      Score:int,
      PerformedActivity:boolean
      >
  >
) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION '/json/students';

Per elencare il nome e il cognome dello studente

SELECT StudentDetails.FirstName, StudentDetails.LastName FROM json_table;

Questo è il risultato ottenuto dalla console di Hive.

Query SerDe 1

Per calcolare la somma dei punteggi del documento JSON

SELECT SUM(scores)
FROM json_table jt
  lateral view explode(jt.StudentClassCollection.Score) collection as scores;

La query precedente usa la funzione definita dall'utente di tipo lateral view explode per espandere la matrice di punteggi, in modo che sia possibile riepilogarli.

Questo è l'output ottenuto dalla console di Hive.

Query SerDe 2

Per trovare le materie in cui un determinato studente ha ottenuto un punteggio superiore a 80:

SELECT  
  jt.StudentClassCollection.ClassId
FROM json_table jt
  lateral view explode(jt.StudentClassCollection.Score) collection as score  where score > 80;

La query precedente restituisce una matrice Hive, a differenza di get_json_object, che restituisce una stringa.

Query SerDe 3

Se si vogliono ignorare documenti JSON non validi, come illustrato nella pagina wiki di questo SerDe, è possibile ottenere questo risultato con il codice seguente:

ALTER TABLE json_table SET SERDEPROPERTIES ( "ignore.malformed.json" = "true");

Summary

In conclusione, il tipo di operatore JSON in Hive scelto dipende dallo scenario. Se è disponibile un documento JSON semplice ed è necessario eseguire ricerche in un solo campo, è possibile scegliere di usare la funzione Hive definita dall'utente get_json_object. Se è necessario cercare più di una chiave, è possibile usare json_tuple. Se è disponibile un documento annidato, è consigliabile usare il SerDe JSON.

Passaggi successivi

Per altri articoli correlati, vedere