Cloudera Impala

Cloudera Impala čini jedan moćan SQL engine za paralelnu obradu ogromnih količina podataka na klasteru.
Da bi smo što približnije objasnili šta je Cloudera Impala i kako ona radi, osvrnimo se na Apache Hadoop sistem. Cloudera je jedna od platformi koja pruža usluge korišćena Apache Impale kao i drugih projekata vezanih za Hadoop tako da ćemo u nastavku dokumenta poistovetiti pojmove Cloudera Impala i Apache Impala.

Hadoop

Apache Hadoop, kao sofverska platforma za distribuirano skladištenje i obradu ogromnih količina podataka (petabajti podataka) sastoji se iz servisa koje pružaju razne mogućnosti upravljanja tim istim podacima. Zbog raznolikosti korisnika koji koriste ovu platformu u pogledu željenog vremena odziva ili raznolikosti potrebnih informacija za njihovo poslovanje/istraživanje, nad njom je razvijeno i nekoliko alata koji su tim potrebama prilagođeni. Dakle hadoop možemo posmatrati kao skup servisa i alata.

Podsetimo se arhitekture hadoop-a. U osnovi hadoop-a nalaze se HDFS (Hadoop Distributed File System) i MapReduce. HDFS je zadužen za čuvanje velikih količina podataka, a MapReduce sistem, pisan u Javi, za njihovu obradu i transformaciju. Ove komponente mogu biti multiplicirane preko više čvorova kreirajući hadoop klaster.

Govoreći o pojedinačnim čvorovima MapReduce server se još zove i TaskTracker koji je zadužen za pokretanje zadatka na određenom čvoru. HDFS server naziva se DataNode i on obezbeđuje velike propusne kapacitete za pristup podacima. Jedan TaskTracker i DataNode čine jednu celinu.

Za upravljanje MapReduce poslovima na različitim mašinama koristi se JobTracker čiji je zadatak balansiranje opterećenja i dodeljivanje poslova različitim TaskTracker-ima. Još jedan od zadataka JobTracker-a je da vodi računa o tome da li su svi TaskTracker-i dostupni, pa da u slučaju kvara prebaci zadatak na drugi čvor. Svaki TaskTracker javlja JobTracker-u o uspešnom ili neuspešnom izvršenju upita. Slično, upravljač DataNode-ova zove se NameNode. NameNode se brine o lokacijama podataka i informaciju o lokaciji prosleđuje korisniku. Dakle sam transfer podataka ne obavlja se kroz NameNode, njegova svrha je da koordinira.

Hadoop arhitektura

Važni alati koji hadoop koriste kao osnovu su:

  • Apache Pig
  • Apache Hive
  • Apache Impala

Apache Pig se može smatrati skripting platformom koja korisnicima hadoop-a omogućava da čak i sa osnovnim znanjem o programiranju pišu kompleksne programe za manipulaciju podacima. Pig ove programe pisane u takozvanom Pig Latin jeziku, koji dosta smanjuje obim koda, prevodi u MapReduce zadatke.

Apache Hive razvijen od strane Facebook-a je alat dizajniran za data warehouse sisteme u cilju olakšanja kompleksnih upita nad ogromnim količinama podataka. Data warehouse možemo zamisliti kao veliko skladište koje prikuplja podatke sa više različitih izvora koje uglavnom čine transakcione aplikacije. Hive je zadužen za izvlačenje, transformaciju i smeštanje (engl. ETL) ovih podatka kao i njihovu obradu i analizu, u procesu u kojem pouzdanost podataka veoma bitna. Hive pomaže u agregaciji i analizi ovih podataka korišćenjem HiveQL-a, jezika koji je sličan SQL-u. Kao i Pig, Hive svoje upite prevodi u MapReduce zadatke.

Hive server

Jedan od bitnih pojmova za Hive infrastrukturu je Hive MetaStore Database. MetaStore je relaciona baza koja sadrži informacije o Hive bazama, tabelama, kolonama, kao i informacije vezane za samu srž hadoop-a tj. informacije o lokacijama blokova podataka na HDFS-u.

Apache Impala za sada pruža najbrže vreme pristupa podacima na HDFS-u. Impala kao i Hive koristi jezik sličan SQL-u, pored čega takođe ima prisutup podacima u MetaStore bazi. Međutim, za razliku od Pig-a i Hive Impala svoje upite ne prevodi u MapReduce zadatke već direktno pristupa podacima sa HDFS-a.

U nastavku teksta proći ćemo korake koji se tiču instalacije jednog manjeg testnog okruženja, a zatim ćemo proći kroz primere i videti kako se performanse Apache Impale porede sa performansama Apache Hive-a.
Razmotrimo prvo najvažnije komponente ovog alata.

Osnovne komponente

Glavna komponenta Impale je pozadinski proces pokrenut na svakome od čvorova sa podacima (HDFS DN – Data Node), takozvani impalad proces. Kada se zahtev uputi nekom čvoru u klasteru, impala servis za taj čvor postaje koordinator upita i bavi se njegovom distribucijom i izvršavanjem, prikupljajući posebne rezultate sa svih ostalih čvorova u klasteru.

Kao koordinator svih impalad procesa StateStore komponenta vodi računa o njihovom statusu. U slučaju kvara na nekom od čvorova statestored proces obaveštava sve ostale impalad procese da ne bi došlo do situacije u kojoj impalad pokušava upit da distribuira na nepostojeći čvor. Dakle StateStore komponenta u sebi sadrži mehanizam za broadcast poruka.

Apache Impala – arhitektura

Naime da bi svaki impalad proces mogao da izvršava upite, on mora biti svestan o svim promenama nad meta podacima u MetaStore-u. Ovo zaduženje obavlja CatalogService komponenta, koja koristeći isti mehanizam za broadcast obaveštava sve impalad procese o promenama nad meta podacima napravljenim od strane drugih impalad procesa.

Obzirom da Impala i Hive imaju deljeni pristup MetaStore-u, u slučaju da Hive izmeni meta podatke, catalogd servise mora uraditi invalidate metadata ili refresh operacije nad bar jednim impalad procesom ne bi li promene bile vidljive u celom sistemu. Invalidate operacija čeka da izmenjeni podaci budu potrebni na korišćenje od strane nekog upita i ponovo učitava sve meta podatke jedne izmenjene celine, što za velike tabele može biti dosta skupa operacija. Refresh sa druge strane ažurira podatke odmah ali, učitava samo informacije o lokacijama blokova koji su izmenjeni.

Instalacija

Cloudera platforma pruža nam mogućnost testiranja Apache Impale na CentOS okruženju postavljenom na virtuelnoj mašini koja se može skinuti putem sledećeg linka. Za pokretanje virtuelne mašine možete iskoristiti alate kao što su Vmware, VirtualBox ili Docker, a biće Vam potreban 64-bitni operativni sistem kao i najmanje 4+ GB rama (oni se moraju dodeliti virtuelnoj mašini).

Ako ste uspešno pokrenuli virtuelnu mašinu primetićete da je podrazumevani korisnik sa korisničkim imenom cloudera, a isto se odnosi i na lozinku. Ovaj korisnik je root korisnik sistema.

Primer

U narednih nekoliko primera pokazujemo način upotrebe Impale, kao i neke osnovne komande za rad sa podacima. Impala mogućnostima se može pristupiti pomoću Hue web aplikacije, ili korišćenjem JDBC ili ODBC interfejsa. U sledećim primerima koristićemo impala-shell alat putem terminala. Terminal za rad možete otvoriti klikom na ikonicu u gornjem levom uglu ili pretragom kroz Applications meni, stavka System Tools.

Da bi ste pristupili impala-shell-u i povezali na instancu impalada potrebno je iskoristiti komandu impala-shell:

[cloudera@quickstart ~]$ impala-shell
#Povezivanje na impalad čija se instanca nalazi na trenutnom host-u
Connected to quickstart.cloudera:21000

Welcome to the Impala shell.
(Impala Shell v2.9.0-cdh5.12.0 (03c6ddb) built on Thu Jun 29 04:17:31 PDT 2017)
[cloudera@quickstart ~]$ impala-shell -i [hostname]
#Opcije za konektovanje na neki drugi host
[cloudera@quickstart ~]$ impala-shell -i [hostname]:[port]

[quickstart.cloudera:21000] > show databases;
Query: show databases
+------------------+---------------------------------------------------------+
| name             | comment                                                 |
+------------------+---------------------------------------------------------+
| _impala_builtins | System database for Impala builtin functions            |
| default          | Default Hive database                                   |
+------------------+---------------------------------------------------------+
Fetched 2 row(s) in 0.15s

Nova Impala instanca uvek ima dve baze. Baza default je trenutna baza, dok je baza _impala_builtins sistemska, i sadrži neke meta podatke i funkcije. Za potrebe ovog primera pratićemo sledeću strukturu podataka uz koju će nam biti potrebna i nova baza. Reč je o uprošćenom sistemu za rezervaciju karti za letove.

Šema baze za rezervaciju letova

Za kreiranje nove baze i odgovarajućih tabela možete iskoristiti sledeće komande:

[quickstart.cloudera:21000] > create database ticket_reservation;
#Kreiranje nove baze
Query: create database ticket_reservation

Fetched 0 row(s) in 0.24s

[quickstart.cloudera:21000] > use ticket_reservation;
#Prebacivanje na rad sa novom bazom
Query: use ticket_reservation

[quickstart.cloudera:21000] > select current_database();
#Prikaz trenutne baze nad kojom se radi
Query: select current_database()
+------------------------+
| current_database()     |
+------------------------+
| ticket_reservation     |
+------------------------+
Fetched 1 row(s) in 0.24s

Što se tipova podataka tiče, u primerima će tip date biti zamenjen tipom timestamp, dok će tip varchar biti zamenjen tipom string. Impala podržava dve vrste tabela:

  1. Interne tabele
  2. Eksterne tabele

Interne tabele se kreiraju podrazumevano. Kod ovih tabela Impala upravlja njihovom unutrašnjom strukturom i fajlovima vezanim za sav unos koji se u slučaju brisanja cele tabele takođe briše.

[quickstart.cloudera:21000] > create table IF NOT EXISTS ticket_types (type_id int, type_name varchar(255), type_pricing double);

#Kreiranje interne tabele ticket_types ukoliko već ne postoji

Query: create table IF NOT EXISTS ticket_types (type_id int, type_name varchar(255), type_pricing double)

Fetched 0 row(s) in 0.76s
[quickstart.cloudera:21000] > show tables;
#Prikazivanje svih tabela za trenutnu bazu
Query: show tables
+--------------+
| name         |
+--------------+
| ticket_types |
+--------------+
Fetched 1 row(s) in 0.08s

Upiti se takođe mogu izvršavati navođenjem putanje do fajla. Da bi ste isprobali ovu mogućnost na lokaciji ~/ kreirajte folder sql i unutar njega kreirajte sql fajl create_tables.sql sa istim sadržajem upita.

[cloudera@quickstart ~]$ impala-shell
[quickstart.cloudera:21000] > use ticket_reservation;
Query: use ticket_reservation
[quickstart.cloudera:21000] > source sql/create_ticket_types.sql;
#Zavisi od lokacije na kojoj se trenutno nalazite

#Izvršavanje upita iz prosleđenog fajla, rezultat isti kao u primeru 3

Query: create table IF NOT EXISTS ticket_types (type_id int, type_name string, type_pricing double)

Fetched 0 row(s) in 0.27s

[quickstart.cloudera:21000] > describe ticket_types;
#Pregled šeme tabele
Query: describe ticket_types
+--------------+--------+------------+
| name         | type   | comment |
+--------------+--------+------------+
| type_id      | int    |                 |
| type_name    | string |            |
| type_pricing | double |            |
+--------------+--------+-----------+
Fetched 3 row(s) in 2.20s
[quickstart.cloudera:21000] > insert into ticket_types values (1,"Eco",2000.00);
Query: insert into ticket_types values (1,"Eco",2000.00)

Modified 1 row(s) in 0.67s
[quickstart.cloudera:21000] > select * from ticket_types order by type_id asc;
Query: select * from ticket_types order by type_id asc
+---------+-----------+-------------------+
| type_id | type_name | type_pricing      |
+---------+-----------+-------------------+
| 1       | Eco       | 2000              |
| 2       | Buss      | 8000              |
+---------+-----------+------------------+
Fetched 2 row(s) in 2.49s

Izaberite neki od načina iz primera i kreirajte internu tabelu tickets sa poljima: 1. ticket_id INT 2. ticket_type INT 3. flight_id INT 4. passenger_id INT 5. price DOUBLE

Eksterne tabele su takve tabele kod kojih se podaci za unos nalaze na lokaciji na HDFS-u, pa čak i u slučaju brisanja cele tabele oni ostaju neizmenjeni. Za naredni primer potrebno je da kreirate podatke za popunjavanje preostalih tabela sa šeme, fajlovi sa podacima mogu biti u csv formatu, dakle razdvojeni zarezom ili bilo kom sličnom formatu, recimo razdvojeni uspravnom crtom. Za kreiranje potrebnih fajlova iskoristite narednu bash skriptu koja fajlove popunjava nasumičnim podacima:

table_data.sh

mkdir -p ~/external_data
cd ~/external_data

for i in {1..10}
  do
    jet_capacity=$(( ( RANDOM % 300 )  + 100 ))
    echo "$i,JetName_$i,JetType_$i,$jet_capacity" >> jets.dat
    echo "$i,CityName_$i" >> cities.dat
    
    passenger_sex="M"
    passenger_age=$(( ( RANDOM % 120 )  + 1 ))
    passenger_random=$(( RANDOM % 2  ))
    if [ $passenger_random -eq 0 ]
    then
    passenger_sex="W"
    fi
    
    echo "$i,PassengerName_$i,PassengerPhone_$i,$passenger_sex,$passenger_age" >> passengers.dat

    echo "$i,$(date '+%Y-%m-%d %H:%M:%S'),$i,$(( ( RANDOM % 90 )  + 1 ))" >> flights.dat
done

counter=1
for ((i=1; i<=10; i++))
 do
  for ((j=i+1; j> miles.dat
     let counter++
     echo "$counter,$j,$i,$miles_random" >> miles.dat
     let counter++    
     fi
  done
done

Lokacija skripte nije bitna, a ukoliko imate problema sa dozvolama za pokretanje upotrebite komandu chmod +x. Skripta table_data.sh kreira po 10 redova za svaku tabelu, sem naravno za tabelu miles, gde kombinuje sve moguće gradove. Fajlove je sada potrebno ubaciti u odgovarajuće foldere na HDFS-u.

Komandom hdfs dfs -ls možete videti strukturu direktorijuma trenutnog korisnika na HDFS-u, cloudera. Pogodno je da nove foldere nazovete po imenima tabela, a evo i primera skripte koju možete iskoristiti za njihovo kreiranje, kao i kreiranje tabela u popunjavanje podacima.

external_tables.sh

hdfs dfs -mkdir /user/cloudera/external_data

hdfs dfs -mkdir /user/cloudera/external_data/cities
hdfs dfs -mkdir /user/cloudera/external_data/jets
hdfs dfs -mkdir /user/cloudera/external_data/flights
hdfs dfs -mkdir /user/cloudera/external_data/passengers
hdfs dfs -mkdir /user/cloudera/external_data/miles

cd ~/external_data

for data in cities jest flights passengers miles
do
    hdfs dfs -put ${data}.dat /user/cloudera/external_data/${data}
done

hdfs dfs -chmod +rw /user/cloudera/external_data/*
hdfs dfs -chmod +rw /user/cloudera/external_data/*/*.dat

hdfs dfs -ls /user/cloudera/external_data/*

Sada kada je postavljena odgovarajuća struktura, tabele možete kreirati na sledeći način: create_external_tables.sql

DROP TABLE IF EXISTS jets;
CREATE EXTERNAL TABLE jets
(
   jet_id INT,
   jet_name STRING,
   jet_type STRING,
   jet_capacity INT
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' – separator kolona
LOCATION '/user/cloudera/external_data/jets'; -- lokacija podataka na hdfs-u

DROP TABLE IF EXISTS cities;
CREATE EXTERNAL TABLE cities
(
   city_id INT,
   city_name STRING
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LOCATION '/user/cloudera/external_data/cities';

DROP TABLE IF EXISTS passengers;
CREATE EXTERNAL TABLE passengers
(
   passenger_id INT,
   passenger_name STRING,
   passenger_phone STRING,
   passenger_sex STRING,
   passenger_age INT
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LOCATION '/user/cloudera/external_data/passengers';

DROP TABLE IF EXISTS miles;
CREATE EXTERNAL TABLE miles
(
   miles_id INT,
   miles_source INT,
   miles_destination INT,
   miles_pricing DOUBLE
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LOCATION '/user/cloudera/external_data/miles';

DROP TABLE IF EXISTS flights;
CREATE EXTERNAL TABLE flights
(
   flight_id INT,
   flight_date TIMESTAMP,
   jet_id INT,
   miles_id INT
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LOCATION '/user/cloudera/external_data/flights';

Sada kada su svi podaci na mestu možemo ih iskoristiti za rezervaciju karti. Putnik Pera Perić želi da rezerviše mesto u avionu, Pera želi da ide bilo gde ali ima ograničen budžet od svega 5000 dinara pa mu ne bi smetalo da bude u ekonomskoj klasi. Prvo je potrebno da proverite da li postoje letovi koji su u okviru Perinog budžeta.

[quickstart.cloudera:21000] > select * from ticket_types where type_name like 'Eco%';

+---------+-----------+-------------------+
| type_id | type_name | type_pricing      |
+---------+-----------+-------------------+
| 1       | Eco       | 2000              |
+---------+-----------+-------------------+
Impala time – 0s, Hive time 0s – (via Hue)

#Nakon provere dodatne cene za ekonomsku kartu, ispotavlja se da Pera ima budžet od 3000 dinara

[quickstart.cloudera:21000] >
select flight_id, source, destination, flight_date, jet_name, jet_capacity, miles_pricing
from 
(
    select flight_id, flight_date, jet_name, jet_type, jet_capacity, miles_id
    from flights
    join jets using(jet_id)
) t1
join
(
    select miles_id, c1.city_name as source, c2.city_name as destination, miles_pricing 
    from miles m 
    join cities c1 
    join cities c2 
    where miles_source = c1.city_id and miles_destination=c2.city_id
) miles using(miles_id);
where miles_pricing <= 3000;



Impala time – 4.57s, Hive time 5m – (via Hue)

Pošto se Peri dopada let 4 potrebno je da proverite da li na tom letu ima mesta.

[quickstart.cloudera:21000] > select count(flight_id) as passenger_number from tickets group by flight_id having flight_id = 4;

+------------------------+
| passenger_number       |
+------------------------+
| 1                      |
+------------------------+

Obzirom da je kapacitet aviona 252, a trenutni broj putnika 1, Pera može rezervisati kartu. Potrebno je da unesete Peru u sistem i rezervišete let.

[quickstart.cloudera:21000] > insert into passengers values(11, ‘Pera’,’Perin telefon’,’M’,22)
                            >insert into tickets values(2, 1, 4, 11, 3147);

Karta je rezervisana i Pera je na putu. Dakle Impala podržava agregacije i spajanja kao i skoro sve standarne tipove podataka sa malo izmenjenom sintaksom sql jezika.

SQL engine-i na Hadoop-u

Kao neke od važnih alata koji rade nad Hadoop-om naveli smo Pig i Hive. Ovi alati su ujedno bili i prvi alati koji nisu radili direktno sa MapReduce zadacima. Pisanje na jeziku sličnom sql-u i/ili lakšem za zadavanje zadataka ove alate mogli su da koriste i ljudi sa malo iskustva u programiranju. Najveći problem ovih alata bio je, a i dalje jeste to što za bilo kakvu manipulaciju podacima koriste MapReduce sistem. MapReduce sistem kreiran je za duge, naporne poslove, zadaci se dugo izvršavaju i treba im vremena da se pokrenu u punom kapacitetu.

Obzirom da su zahtevi za većom brzinom izvršavanja i pristupom podacima u realnom vremenu sve veći, danas postoji nekoliko alata koji zadovoljavaju te potrebe. Neki od njih su Impala i Presto.

Na kraju imamo različite alata koji su prilagođeni različitim potrebama a pritom ih je nemoguće spojiti u jedan univerzalni alata. Cilj svih ovih prozvoda je da imaju što bolje performanse i da pružaju širok spektar usluga. U nastavku objašnjavamo razliku u performansama Impale i Hive-a ne bi li videli uzrok nastajanja različitih engine-a.

Impala vs. Hive

Iako je Impala dosta brža od Hive-a ne znači da je bolji izbor koristiti je za sve probleme. Impala je memorijski zahtevija i ne izvršava efikasno određene operacije, posebno kada su baš velike količine podataka u pitanju. Dakle ukoliko je potrebno serijski obraditi veliku količinu podataka, Hive je bolje rešenje, a ukoliko je potrebna brza obrada podataka i malo kašnjenje, bolje je izabrati Impalu.

Za primere kojima ćemo uporediti performanse Hive-a i Impale koristi se malo drugačija struktura podataka u odnosu na prethodne primere.

Podaci za testiranje određenih upita nalaze se na sledećem linku.

  • Potrebno je skinuti i raspakovati sledeći fajl TPC-DS_Tools_v2.5.0.zip, tj. source code za Benchmark TPC-DS.
  • Fajl je potrebno raspakovati na lokaciju /home/cloudera pod nazivom tpcds.
  • Sledeći korak je prebacivanje potrebnih fajlova kao i kreiranje određene strukture direktorijuma na osnovu koje će se kreirati tabele. Ovo možete uraditi pokretanjem skripte tpcds-setup.sh, koja će biti data u nastavku. Vodite računa o tome da ste dobro postavili lokaciju u koraku dva. Da bi ste iz ove skripte pozvali skriptu za kreiranje tabela izmenite lokaciju u poslednjem redu.

Ukoliko je potrebno postaviti dozvole nad skriptom za njeno pokretanje, to možete uraditi u terminalu komandom chmod +x tpcds-setup.sh, a zatim je i pokrenuti ./tpcds-setup.sh.

tpcds-setup.sh

#!/bin/bash

cd ~/tpcds
cd tools
make clean
make
export PATH=$PATH:.
DIR=$HOME/tpcds/data
mkdir -p $DIR
SCALE=1
FORCE=Y

#Skripta za generisanje podataka dsdgen
dsdgen -verbose -force $FORCE -dir $DIR -scale $SCALE -table store_sales
dsdgen -verbose -force $FORCE -dir $DIR -scale $SCALE -table date_dim
dsdgen -verbose -force $FORCE -dir $DIR -scale $SCALE -table time_dim
dsdgen -verbose -force $FORCE -dir $DIR -scale $SCALE -table item
dsdgen -verbose -force $FORCE -dir $DIR -scale $SCALE -table customer
dsdgen -verbose -force $FORCE -dir $DIR -scale $SCALE -table customer_demographics
dsdgen -verbose -force $FORCE -dir $DIR -scale $SCALE -table household_demographics
dsdgen -verbose -force $FORCE -dir $DIR -scale $SCALE -table customer_address
dsdgen -verbose -force $FORCE -dir $DIR -scale $SCALE -table store
dsdgen -verbose -force $FORCE -dir $DIR -scale $SCALE -table promotion

hdfs dfs -mkdir /user/hive/tpcds

hdfs dfs -mkdir /user/hive/tpcds/date_dim
hdfs dfs -mkdir /user/hive/tpcds/time_dim
hdfs dfs -mkdir /user/hive/tpcds/item
hdfs dfs -mkdir /user/hive/tpcds/customer
hdfs dfs -mkdir /user/hive/tpcds/customer_demographics
hdfs dfs -mkdir /user/hive/tpcds/household_demographics
hdfs dfs -mkdir /user/hive/tpcds/customer_address
hdfs dfs -mkdir /user/hive/tpcds/store
hdfs dfs -mkdir /user/hive/tpcds/promotion
hdfs dfs -mkdir /user/hive/tpcds/store_sales
hdfs dfs -mkdir /user/hive/tpcds/store_returns

cd $HOME/tpcds/data

for t in date_dim time_dim item customer customer_demographics household_demographics customer_address store promotion store_sales store_returns
do
      hdfs dfs -put ${t}.dat /user/hive/tpcds/${t} 
done
hdfs dfs -ls -R /user/hive/tpcds/*/*.dat

#Kreiranje tabela putem Hive-a, potrebno je da se navede lokacija skripte tpcds_ss_tables.sql
hive -f /home/cloudera/impalascripts/tpcds_ss_tables.sql

tpcds_ss_tables.sql

create external table store_returns
(
    sr_returned_date_sk       int,
    sr_return_time_sk         int,
    sr_item_sk                int,
    sr_customer_sk            int,
    sr_cdemo_sk               int,
    sr_hdemo_sk               int,
    sr_addr_sk                int,
    sr_store_sk               int,
    sr_reason_sk              int,
    sr_ticket_number          bigint,
    sr_return_quantity        int,
    sr_return_amt             float,
    sr_return_tax             float,
    sr_return_amt_inc_tax     float,
    sr_fee                    float,
    sr_return_ship_cost       float,
    sr_refunded_cash          float,
    sr_reversed_charge        float,
    sr_store_credit           float,
    sr_net_loss               float             
)
row format delimited fields terminated by '|' 
location '/user/hive/tpcds/store_returns';

create external table store_sales
(
    ss_sold_date_sk           int,
    ss_sold_time_sk           int,
    ss_item_sk                int,
    ss_customer_sk            int,
    ss_cdemo_sk               int,
    ss_hdemo_sk               int,
    ss_addr_sk                int,
    ss_store_sk               int,
    ss_promo_sk               int,
    ss_ticket_number          int,
    ss_quantity               int,
    ss_wholesale_cost         float,
    ss_list_price             float,
    ss_sales_price            float,
    ss_ext_discount_amt       float,
    ss_ext_sales_price        float,
    ss_ext_wholesale_cost     float,
    ss_ext_list_price         float,
    ss_ext_tax                float,
    ss_coupon_amt             float,
    ss_net_paid               float,
    ss_net_paid_inc_tax       float,
    ss_net_profit             float                  
)
row format delimited fields terminated by '|' 
location '/user/hive/tpcds/store_sales';

create external table customer_demographics
(
    cd_demo_sk                int,
    cd_gender                 string,
    cd_marital_status         string,
    cd_education_status       string,
    cd_purchase_estimate      int,
    cd_credit_rating          string,
    cd_dep_count              int,
    cd_dep_employed_count     int,
    cd_dep_college_count      int 
)
row format delimited fields terminated by '|' 
location '/user/hive/tpcds/customer_demographics';

create external table date_dim
(
    d_date_sk                 int,
    d_date_id                 string,
    d_date                    timestamp,
    d_month_seq               int,
    d_week_seq                int,
    d_quarter_seq             int,
    d_year                    int,
    d_dow                     int,
    d_moy                     int,
    d_dom                     int,
    d_qoy                     int,
    d_fy_year                 int,
    d_fy_quarter_seq          int,
    d_fy_week_seq             int,
    d_day_name                string,
    d_quarter_name            string,
    d_holiday                 string,
    d_weekend                 string,
    d_following_holiday       string,
    d_first_dom               int,
    d_last_dom                int,
    d_same_day_ly             int,
    d_same_day_lq             int,
    d_current_day             string,
    d_current_week            string,
    d_current_month           string,
    d_current_quarter         string,
    d_current_year            string 
)
row format delimited fields terminated by '|' 
location '/user/hive/tpcds/date_dim';

create external table time_dim
(
    t_time_sk                 int,
    t_time_id                 string,
    t_time                    int,
    t_hour                    int,
    t_minute                  int,
    t_second                  int,
    t_am_pm                   string,
    t_shift                   string,
    t_sub_shift               string,
    t_meal_time               string
)
row format delimited fields terminated by '|' 
location '/user/hive/tpcds/time_dim';

create external table item
(
    i_item_sk                 int,
    i_item_id                 string,
    i_rec_start_date          timestamp,
    i_rec_end_date            timestamp,
    i_item_desc               string,
    i_current_price           float,
    i_wholesale_cost          float,
    i_brand_id                int,
    i_brand                   string,
    i_class_id                int,
    i_class                   string,
    i_category_id             int,
    i_category                string,
    i_manufact_id             int,
    i_manufact                string,
    i_size                    string,
    i_formulation             string,
    i_color                   string,
    i_units                   string,
    i_container               string,
    i_manager_id              int,
    i_product_name            string
)
row format delimited fields terminated by '|' 
location '/user/hive/tpcds/item';

create external table store
(
    s_store_sk                int,
    s_store_id                string,
    s_rec_start_date          timestamp,
    s_rec_end_date            timestamp,
    s_closed_date_sk          int,
    s_store_name              string,
    s_number_employees        int,
    s_floor_space             int,
    s_hours                   string,
    s_manager                 string,
    s_market_id               int,
    s_geography_class         string,
    s_market_desc             string,
    s_market_manager          string,
    s_division_id             int,
    s_division_name           string,
    s_company_id              int,
    s_company_name            string,
    s_street_number           string,
    s_street_name             string,
    s_street_type             string,
    s_suite_number            string,
    s_city                    string,
    s_county                  string,
    s_state                   string,
    s_zip                     string,
    s_country                 string,
    s_gmt_offset              float,
    s_tax_precentage          float                  
)
row format delimited fields terminated by '|' 
location '/user/hive/tpcds/store';

create external table customer
(
    c_customer_sk             int,
    c_customer_id             string,
    c_current_cdemo_sk        int,
    c_current_hdemo_sk        int,
    c_current_addr_sk         int,
    c_first_shipto_date_sk    int,
    c_first_sales_date_sk     int,
    c_salutation              string,
    c_first_name              string,
    c_last_name               string,
    c_preferred_cust_flag     string,
    c_birth_day               int,
    c_birth_month             int,
    c_birth_year              int,
    c_birth_country           string,
    c_login                   string,
    c_email_address           string,
    c_last_review_date        string
)
row format delimited fields terminated by '|' 
location '/user/hive/tpcds/customer';

create external table promotion
(
    p_promo_sk                int,
    p_promo_id                string,
    p_start_date_sk           int,
    p_end_date_sk             int,
    p_item_sk                 int,
    p_cost                    float,
    p_response_target         int,
    p_promo_name              string,
    p_channel_dmail           string,
    p_channel_email           string,
    p_channel_catalog         string,
    p_channel_tv              string,
    p_channel_radio           string,
    p_channel_press           string,
    p_channel_event           string,
    p_channel_demo            string,
    p_channel_details         string,
    p_purpose                 string,
    p_discount_active         string 
)
row format delimited fields terminated by '|' 
location '/user/hive/tpcds/promotion';

create external table household_demographics
(
    hd_demo_sk                int,
    hd_income_band_sk         int,
    hd_buy_potential          string,
    hd_dep_count              int,
    hd_vehicle_count          int
)
row format delimited fields terminated by '|' 
location '/user/hive/tpcds/household_demographics';

create external table customer_address
(
    ca_address_sk             int,
    ca_address_id             string,
    ca_street_number          string,
    ca_street_name            string,
    ca_street_type            string,
    ca_suite_number           string,
    ca_city                   string,
    ca_county                 string,
    ca_state                  string,
    ca_zip                    string,
    ca_country                string,
    ca_gmt_offset             float,
    ca_location_type          string
)
row format delimited fields terminated by '|' 
location '/user/hive/tpcds/customer_address';

quit;
  • Sada je potrebno da zadavanjem komande impala-shell -r obavestite Impala procese da je došlo do izmene meta podataka.
  • Ukoliko je sve prošlo kako treba, upotrebom komande show tables bi trebalo da dobijete sledeći rezultat.
[quickstart.cloudera:21000] > show tables;
Query: show tables
+------------------------+
| name                   |
+------------------------+
| customer               |
| customer_address       |
| customer_demographics  |
| date_dim               |
| household_demographics |
| item                   |
| promotion              |
| store                  |
| store_returns          |
| store_sales            |
| time_dim               |
+------------------------+
Fetched 11 row(s) in 0.11s

Za izvršavanje upita možete koristiti konzolu ili alat kao što je Hue koji je malo više orijentisan na korisnike. Hue je web aplikacija za analizu, manipulaciju i deljenje podataka. Omogućava uvid u baze i tabele, a rezultati se sem tabelarno mogu predstaviti u obliku grafikona. U kombinaciji sa jezikom koji podseća na sql krajnje je lak za korišćenje.

Hue

Još jedan od razloga za korišćenje Hue-a, jednim klikom na dugme lako možemo prelaziti sa Hive-a na Impalu i obrnuto, pa je testiranje i poređenje performansi utoliko lakše.

Ovo su neki od izdvojenih rezultata testiranja na virtuelnoj mašini za ubrzano učenje koje obezbeđuje Cloudera.

Impala Hive Upit
7.84s 7m 37s 55.sql
8.78s 5m 29s 3.sql
23.11s 9m 27s 27.sql
30s 19m 11s 17.sql
41.36s 30m + 1.sql

Kao što možemo videti, Impala zaista ima dosta bolje performanse od Hive-a, ali ovi rezultati mogu dosta zavisiti od količine test podataka kao i mašina na kojima se zadaci izvršavaju. Jedan od razloga zašto se Hive duže izvršava je i startup ovehead, MapReduce zadacima je potrebno neko vreme da iskoriste pun kapacitet čvorova.

Prednost Hive-a je velika tolerancija na greške, naime ako dođe do kvara čvora sa podacima, korisnik će ipak dobiti rezultat, dok se kod Impale ceo upit mora pokrenuti ponovo. Hive ima veliku toleranciju baš zato što je zadužen za obrade koje drugo traju, dakle i po nekoliko sati.

Upiti su birani po kompleksnosti, kojoj doprinosi veći broj spajanja, agregacija, ugnježdavanja ili brojem podataka koji proizvedu.

3.sql

select  dt.d_year 
       ,item.i_brand_id brand_id 
       ,item.i_brand brand
       ,sum(ss_ext_sales_price) sum_agg
 from  date_dim dt 
      ,store_sales
      ,item
 where dt.d_date_sk = store_sales.ss_sold_date_sk
   and store_sales.ss_item_sk = item.i_item_sk
   and item.i_manufact_id = 436
   and dt.d_moy=12
 group by dt.d_year
      ,item.i_brand
      ,item.i_brand_id
 order by dt.d_year
         ,sum_agg desc
         ,brand_id
 limit 100;

55.sql

select  i_brand_id brand_id, i_brand brand,
    sum(ss_ext_sales_price) ext_price
 from date_dim, store_sales, item
 where date_dim.d_date_sk = store_sales.ss_sold_date_sk
    and store_sales.ss_item_sk = item.i_item_sk
    and i_manager_id=36
    and d_moy=12
    and d_year=2001
 group by i_brand, i_brand_id
 order by ext_price desc, i_brand_id
limit 100 ;

17.sql

select  i_item_id
       ,i_item_desc
       ,s_state
       ,count(ss_quantity) as store_sales_quantitycount
       ,avg(ss_quantity) as store_sales_quantityave
       ,stddev_samp(ss_quantity) as store_sales_quantitystdev
       ,stddev_samp(ss_quantity)/avg(ss_quantity) as store_sales_quantitycov
       ,count(sr_return_quantity) as_store_returns_quantitycount
       ,avg(sr_return_quantity) as_store_returns_quantityave
       ,stddev_samp(sr_return_quantity) as_store_returns_quantitystdev
       ,stddev_samp(sr_return_quantity)/avg(sr_return_quantity) as store_returns_quantitycov
 from store_sales
     ,store_returns
     ,date_dim d1
     ,date_dim d2
     ,store
     ,item
 where d1.d_quarter_name = '2000Q1'
   and d1.d_date_sk = store_sales.ss_sold_date_sk
   and item.i_item_sk = store_sales.ss_item_sk
   and store.s_store_sk = store_sales.ss_store_sk
   and store_sales.ss_customer_sk = store_returns.sr_customer_sk
   and store_sales.ss_item_sk = store_returns.sr_item_sk
   and store_sales.ss_ticket_number = store_returns.sr_ticket_number
   and store_returns.sr_returned_date_sk = d2.d_date_sk
   and d2.d_quarter_name in ('2000Q1','2000Q2','2000Q3')
 group by i_item_id
         ,i_item_desc
         ,s_state
 order by i_item_id
         ,i_item_desc
         ,s_state
limit 100;

27.sql

select  i_item_id,
        s_state,
        avg(ss_quantity) agg1,
        avg(ss_list_price) agg2,
        avg(ss_coupon_amt) agg3,
        avg(ss_sales_price) agg4
 from store_sales, customer_demographics, date_dim, store, item
 where store_sales.ss_sold_date_sk = date_dim.d_date_sk and
       store_sales.ss_item_sk = item.i_item_sk and
       store_sales.ss_store_sk = store.s_store_sk and
       store_sales.ss_cdemo_sk = customer_demographics.cd_demo_sk and
       customer_demographics.cd_gender = 'F' and
       customer_demographics.cd_marital_status = 'D' and
       customer_demographics.cd_education_status = 'Unknown' and
       date_dim.d_year = 1998 and
       store.s_state in ('KS','AL', 'MN', 'AL', 'SC', 'VT')
 group by i_item_id, s_state
 order by i_item_id
         ,s_state
 limit 100;

1.sql

select  *
from store_sales
    ,store_returns
    ,date_dim d1
    ,store
    ,item
    ,customer
    ,customer_address
    ,customer_demographics
    ,household_demographics
    ,time_dim
    ,promotion

Šabloni upiti koje možete iskoristiti za kreiranje upita za testiranje nalaze se na lokaciji ~/tcpds/query_templates.

Literatura

  1. Impala tutorijal – https://www.cloudera.com/documentation/enterprise/5-8-x/topics/impala.html
  2. Hue – https://www.cloudera.com/documentation/enterprise/5-8-x/topics/hue.html
  3. Hive vs. Impala – https://www.dezyre.com/article/hive-vs-impala-sql-war-in-the-hadoop-ecosystem/148
  4. Quick start – http://blog.cloudera.com/blog/2013/06/quickstart-vm-now-with-real-time-big-data
  5. Dodatne informacije – http://blog.cloudera.com blog/2013/06/quickstart-vm-now-with-real-time-big-data
  6. Podaci za testiranje – http://www.tpc.org/tpc_documents_current_versions/current_specifications.asp