SQL Hadoop felett - Apache Hive

Összefoglalás

Ez az olvasólecke gyakorlati tudást ad a Hive SQL-alapú lekérdező réteg használatáról. Iránymutatást adunk arra nézve, hogyan lehet a Hive eszközt telepíteni, illetve virtualizált környezetben elindítani. Konkrét példákon keresztül bemutatjuk, hogyan lehet lokális fájlrendszerről, vagy a HDFS-en tárolt adatfájlokat betölteni, és hozzájuk SQL lekérdezéseket írni. Foglalkozunk a tabulált fájlok, valamint a struktúrát szövegek (pl. log bejegyzések és JSON) betöltésének módjaival a Hive kliens segítségével. E mellett betekintést kaphat az olvasó abba, hogyan lehet a Hive adattáblákat Java programkódból elérni a klasszikus JDBC API segítségével.
A lecke fejezetei:
  • 1. fejezet: Apache Hive indítása Docker környezetben, tabulált szöveges állományok betöltése (olvasó)
  • 2. fejezet: Struktúrált szöveg fájlok beolvasása (napló bejegyzések és JSON) beépített SerDe megvalósításokkal (olvasó)
  • 3. fejezet: Apache Hive Java programból történő elérése JDBC API-n keresztül (olvasó)
Téma típusa: gyakorlati
Olvasási idő: 50 perc

Book to read, knowledge, lecture, open book, reading book icon 1. fejezet

Apache Hive indítása, tabulált szöveges adatok betöltése

Ahogy a kapcsolódó előadás olvasóleckéiben (6e_BigData-sql-over-hadoop-SPOC) már láttuk, az Apache Hive [1] egy SQL lekérdező és feldolgozó absztrakciós réteg a HDFS-en tárolt adatfájlok fölé. Ebben a fejezetben bemutatjuk hogyan lehet tabulált szövegfájlokat betölteni a Hive adattábláiba és azokon SQL lekérdezéseket végezni.

Telepítés/docker konténerek Hive-hoz

A Hive telepítése a megfelelő bináris csomag letöltéséből, kicsomagolásából, valamint a környezeti változók és konfigurációs állományok beállításából áll. Részletek a hivatalos dokumentációban [2] olvashatók. Mi a lokális gépre történő telepítés helyett egy előre előkészített docker container stack-et fogunk használni, mert a Hive használatához egy Hadoop klaszterre is szükség van. A következőkben bemutatott stack az összes szükséges docker image-t elindítja, ami szükséges a Hive azonnali használatához. A következő példák tetszőleges gépen futtathatók, ahol telepítve van a Dokcer környezet, valamint a Git verziókövető kliens.

A Hive stack indításához először töltsük le a docker leírókat és a teljes stack konfigurációt tartalmazó git repository-t a következő parancs segítségével:

A letöltött docker-hive mappa tartalmazza a docker-compose.yml stack konfigurációt, ebben láthatjuk milyen szolgáltatások (docker image-ek) indulnak el a Hive használatához:

A stack indításához lépjünk be a docker-hive mappába, és adjuk ki a következő docker parancsot:

A stack sikeres indítása után a következő paranccsal ellenőrizhetjük, hogy minden container sikeresen elindult:

Windows felhasználók figyelem!
Amennyiben Windows host-on indítjuk a docker stack-et, és a következő hibaüzenetet kapjuk "ERROR: for namenode Cannot start service namenode: Ports are not available: listen tcp 0.0.0.0:50070: bind: An attempt was made to access a socket in a way forbidden by its access permissions.", az azért van, mert a dokcer daemon bizonyos portokat lefoglal magának, amivel ütközik a docker konfigurációnk. A legegyszerűbb megoldás, ha módosítjuk a docker-compose.yml fájlt, és minden 50000-en felüli portszám esetén a mapping-et átírjuk, pl. - "50070:50070" helyett legyen - "30070:50070".

Tabulált szöveges adatok betöltése Hive-ba a lokális fájlrendszerről

Először lépjünk be a hive-server container-be és indítsunk egy terminált a következő parancs segítségével:

Először egy Hive-os példa szövegfájl, az examples/files/employee_part.txt tartalmát töltjük be egy Hive adattáblába. A szövegfájl tartalma a következő:

Ezt a fájl a HIve a lokális fájlrendszerből be tudja tölteni és elérhetővé tenni SQL lekérdezésekhez. Mielőtt ezt azonban meg tudná tenni, definiálnunk kell az adatok struktúráját, hasonlóan, ahogy egy relációs adatbázis esetén definiálja a tábla sémáját. Az adatmodell leíró nyelv (Data Definition Language - DDL) hasonló az SQL nyelvhez, bővebben a hivatalos dokumentáció DDL-t ismertető részéből [4] tudunk tájékozódni. A fenti tabulált szövegfájl tartalomhoz hozzuk létre a következő adattáblát (employee.hql):

Négy mezőt definiálunk a szövegfájl oszlopainak megfelelően, majd a ROW FORMAT DELIMITED utasítással jelezzük, hogy tabulált szöveg az adatforrás. A FIELDS TERMINATED BY '|' utasítással megadjuk, hogy a mező elválasztó karakter a |. Az utolsó utasítás azt jelzi, hogy az adatok szöveges fájlként léteznek. Ezután készen állunk a Hive parancssor elindítására (a két lehetőség közül az újabb és preferált beeline klienst használjuk, aminek egyetlen JDBC URL paramétere van) és a tábla leíró betöltésére. Ehhez a docker container-en belül adjuk ki a következő parancsot:

A Hive Metastore-ban eltárolódott az új táblánk leírója, most már kiadhatjuk az adat lokális fájlrendszerről való betöltését kezdeményező parancsot a beeline terminálból:

Ha a parancs hibaüzenet nélkül lefutott, most már készen állunk arra, hogy a tabulált szövegként létező adaton SQL lekérdezéseket hajtsunk végre. Amennyiben a tábla már tartalmazott adatokat, azok az OVERWRITE kulcsszó miatt felülíródnak. Próbáljuk ki a következő lekérdezéseket:

A második lekérdezés warning üzenete beszédes. Kiderül belőle, hogy a Hive MapReduce job-bá konvertálja az SQL-ben megfogalmazott lekérdezéseket, és az előálló eredményt adja vissza. Az is kiderül az üzenetből, hogy ez a módszer már túlhaladott (és nem a leghatékonyabb), a legújabb Hive használatakor érdemes megfontolni az Apache Spark [5] vagy Apache Tez [6] végrehajtó motor használatát a klasszikus MapReduce helyett.

Tabulált szöveges adatok betöltése Hive-ba HDFS-ről

Nem csak a Hive lokális fájlrendszeréből tudunk adatokat betölteni és lekérdezni, hanem természetesen a HDFS-en már létező fájlokra is ún. külső (external) táblákat tudunk illeszteni. Ehhez példaként használjuk fel a sales_enrties.csv állományt a 2g_BigData-data-transform-SPOC gyakorlatról. Először másoljuk be a csv fájlt a lokális gépünkről a NameNode-ot futtató docker container-be, majd onnan a HDFS-re az alábbi parancsok segítségével:

Hozzuk létre a sales_entries.csv-nek megfelelő táblát Hive-ban:

Az utasítás majdnem ugyanúgy néz ki mint az imént. A különbség (a más elválasztó karakteren kívül), hogy az EXTERNAL kulcsszót használtuk az elején, és a végén egy LOCATION paranccsal megadtuk az előbb feltöltött csv fájlt tartalmazó mappa elérési útvonalát HDFS-en (a TBLPROPERTIES segítségével beállítottuk, hogy a fejléc sort hagyja ki a csv feldolgozásból). Ez azt jelenti a Hive számára, hogy az adatok már léteznek, azt nem kell neki létrehozni HDFS-en az alapértelmezett helyre. Nincs is ezután szükség a LOAD utasításra, a csv fájl azonnal lekérdezhető SQL-lel:

Book to read, knowledge, lecture, open book, reading book icon 2. fejezet

Egyéb strukturált szövegfájlok betöltése Hive-ba

Szövegfájlok betöltése reguláris kifejezéssel

A fentiekben bemutattuk a tabulált szövegfájlok betöltésének módjait. Sokszor előfordul azonban, hogy a lekérdezni kívánt adatfájl nem tabulált, de valamilyen egységes formában tartalmaz információt. Tipikus példa a log fájlok, ahol minden sor azonos felépítésű, de az adatok nem tagolódnak mezőkre. A Hive lehetőséget ad az ilyen fájlok közvetlen betöltésére és SQL lekérdezésére is reguláris kifejezések segítségével (ezen kívül több fajta szerializáló/deszerializáló metódust is tartalmaz beépítve [7]). A fájl típusának meghatározásakor a beépített RegexSerDe módot kell választani, és egy reguláris kifejezéssel megadni, hogy a szövegfájl egyes részei milyen mezők értékeire képződjenek le. Tekintsük az alábbi példa log fájlt (sample.log):

Ha ebből a logból minden bejegyzés esetén szeretnénk kinyerni az IP címet, a log bejegyzés napját és az elért URL címét, az alábbi Hive tábla definíciót használhatjuk (a sample.log fájlt másoljuk fel a Hive container-be és lokális adatként töltsük be a táblába):

A reguláris kifejezés három illeszkedő minta része alkotja majd az egyes sorok mezőinek értékeit. A fenti adatok betöltése után a táblánk tartalma a következő:

Adatok betöltése JSON fálból

Létezik beépített JSON SerDe megoldás is, amivel közvetlenül JSON fájlból tudunk adattáblát feltölteni. Hozzunk létre egy táblát a personal_entries.json állományban tárolt adatokhoz (lásd 2g_BigData-data-transform-SPOC gyakorlati anyag):

Ezután le is kérdezhetjük a JSON-ben lévő adatokat:

Sőt, JOIN művelettel akár össze is kapcsolhatjuk a sales_entries.csv tartalmával, hiszen azt is betöltöttük egy Hive táblába:

Book to read, knowledge, lecture, open book, reading book icon 3. fejezet

Hive programozása Java-ban JDBC API-n keresztül

Mivel a Hive egy JDBC driver-t is nyújt az adatok eléréséhez (amit egyébként a beeline kliens is használ az adatok eléréséhez), a Hive könnyen használható Java kódból is a JDBC API- keresztül. Gyakorlatilag úgy programozhatjuk a HDFS-en lévő adatfájlok Hive rétegen keresztüli SQL lekérdezéseit, mintha egy klasszikus relációs adatbázishoz csatlakoznánk. Példaként tekintsük az alábbi Java programot (org/example/HiveJDBCClient.java), ami kilistázza a personal_entries.json fájl tartalmát a personal_entries Hive adattábla lekérdezése által:

A program fordítása és futtatása a következő parancsokkal végezhető el:

Ahhoz, hogy a csatlakozás sikeres legyen a fenti Hive docker stack-nek futnia kell (a Hive szerver 10000-es portja forwardolva van localhost-ra is, ezért működik a lokális csatlakozás). Fontos, hogy a futtatásnak van pár függősége, amiket a lib könyvtárból töltünk be, ez első sorban a Hive JDBC driver, valamint a HTTP kommunikációhoz szükséges könyvtárak.

Check mark icon set. Green OK or V tick, red X, exclamation mark ...További feladatok

  1. Töltsük be a billing_entries.json fájlt is egy Hive táblába (teljes cím adatokkal), és írjunk egy olyan SQL lekérdezést, ami mindhárom adatforrást (personal_entries.json, billing_entries.json, sales_entries.csv) összekapcsolja a PID alapján!
  2. Írjunk egy olyan Java programot, ami a Hive JDBC driver segítségével lekérdezi azokat a személyeket a personal_entries.json és sales_entries.csv fájlokból, akik 1970 után születtek, és kaptak ajánlatot (offer_text mező nem üres)!
  3. Kérdezzük le Apache Drill [8] segítségével a personal_entries.json tartalmát HDFS-ről!
  4. Kapcsoljuk össze Apache Drill [8] segítségével a personal_entries.json, billing_entries.json, valamint asales_entries.csv tartalmát egy lekérdezéssel!
  5. A gyakorlatban bemutatott lekérdezéseket hajtsuk végre Apache Imapala (docker stack [9] használható) segítségével is (használjuk az imapla-shell-t és a fenti adat definíciókat)!

Referenciák

[1] https://hive.apache.org/

[2] https://cwiki.apache.org/confluence/display/Hive/GettingStarted#GettingStarted-InstallationandConfiguration

[3] https://bigdataprogrammers.com/load-csv-file-in-hive/

[4] https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL

[5] https://spark.apache.org/

[6] https://tez.apache.org/

[7] https://cwiki.apache.org/confluence/display/Hive/SerDe

[8] https://drill.apache.org/

[9] https://github.com/parrot-stream/docker-impala