Partiții și găleți Hive cu exemplu

⚡ Rezumat inteligent

Partițiile și compartimentele (buckets) sunt cele două moduri în care Apache Hive împarte datele din tabele pe disc: o partiție creează un director per valoare cheie, în timp ce un compartiment (bucket) împarte rândurile într-un număr fix de fișiere.

  • 🗂️ Partiția este un director: Fiecare valoare distinctă a cheii de partiție devine propriul subdirector în folderul tabelului din HDFS.
  • ✂️ Tăierea partițiilor: O interogare care filtrează după cheia de partiție citește doar directoarele corespondente în loc să scaneze întregul tabel.
  • ⚙️ Mod dinamic necesar: Încărcarea mai multor partiții dintr-un SELECT necesită ca hive.exec.dynamic.partition.mode să fie setat la nonstrict.
  • 🧮 Bucket este un fișier: CLUSTERED BY hashează coloana aleasă și scrie fiecare rând într-unul dintr-un număr fix de fișiere.
  • 🔍 Eșantionare și îmbinări: Tabelele cu compartimente acceptă citiri TABLESAMPLE eficiente și joncțiuni de compartimente pe partea de hartă, lucru pe care tabelele simple nu îl pot face.
  • 📐 Alegeți după cardinalitate: Partiționare pe coloane cu cardinalitate scăzută, cum ar fi starea sau data, și pe coloane cu cardinalitate ridicată de tip bucket, cum ar fi identificatorii de utilizator.

Partiții și găleți Hive explicate cu un exemplu practic

Tabelele, Partițiile și Bucket-urile sunt părți ale modelării datelor Hive. Un tabel definește schema, o partiție împarte acel tabel în directoare pe disc, iar un bucket împarte datele dintr-un director într-un număr fix de fișiere.

Ce este Partitions?

Partițiile Hive reprezintă o modalitate de a organiza tabelele în partiții prin împărțirea tabelelor în diferite părți pe baza cheilor de partiție. Fizic, fiecare partiție este un subdirector separat în folderul tabelului din HDFS, ceea ce permite Hive să sară peste datele de care nu are nevoie.

Partiționarea este utilă atunci când tabelul are una sau mai multe chei de partiție. Cheile de partiție sunt elemente de bază pentru a determina modul în care datele sunt stocate în tabel. O cheie de partiție nu este stocată în fișierele de date în sine - valoarea sa este codificată în numele directorului, astfel încât o filtrare a interogărilor pe acea cheie poate elimina directoare întregi înainte de a fi citit orice rând. Aceasta se numește eliminare a partițiilor.

De exemplu: –

„Clientul are date de comerț electronic care aparțin operațiunilor din India, în care operațiunile din fiecare stat (38 de state) sunt menționate ca un întreg. Dacă luăm coloana de stare drept cheie de partiție și efectuăm partiții pe baza datelor din India în ansamblu, putem obține numărul de partiții (38 de partiții), care este egal cu numărul de state (38) prezente în India. Astfel încât datele pentru fiecare stat să poată fi vizualizate separat în tabelele de partiții.”

Eşantion Code Fragment pentru partiții

Cele șase instrucțiuni de mai jos rulează în ordine în shell-ul Hive. Fiecare este un pas separat, iar capturile de ecran care urmează arată aceeași secvență executându-se pe un cluster live.

  1. Crearea tabelului allstates
    create table allstates(state string, District string,Enrolments string)
    
    row format delimited
    
    fields terminated by ',';
    
  2. Încărcarea datelor în tabelul allstates creat
    Load data local inpath '/home/hduser/Desktop/AllStates.csv' into table allstates;
  3. Crearea tabelului de partiții
    create table state_part(District string,Enrolments string) PARTITIONED BY(state string);
  4. Pentru partiție trebuie să setăm această proprietate
    set hive.exec.dynamic.partition.mode=nonstrict
  5. Încărcarea datelor în tabelul de partiții
    INSERT OVERWRITE TABLE state_part PARTITION(state)
    SELECT district,enrolments,state from  allstates;
  6. Procesarea efectivă și formarea tabelelor de partiții pe baza stării ca cheie de partiție

Vor exista 38 de ieșiri de partiție în spațiul de stocare HDFS cu numele fișierului ca nume de stare. Vom verifica acest lucru în acest pas.

Următoarele capturi de ecran prezintă execuția codului menționat mai sus.

În primul ecran, pasul 1 se execută la stup prompt și creează allstate tabel cu cele trei coloane ale sale și o virgulă ca delimitator de câmp.

Shell Hive care creează tabelul allstates cu trei coloane delimitate

Următorul ecran acoperă pașii 2 și 3: fișierul AllStates.csv este încărcat în allstateși tabelul partiționat parte_de_stare este creat cu starea declarată ca și cheie de partiție.

Încărcarea fișierului AllStates.csv în allstates și crearea tabelului partiționat state_part

Pașii 4 și 5 apar în continuare. Modul de partiție dinamică este setat la nonstrict, iar instrucțiunea INSERT OVERWRITE lansează un job MapReduce ale cărui linii de jurnal arată câte o partiție încărcată pentru fiecare valoare de stare.

Rezultatul jobului MapReduce încarcă o partiție Hive per valoare de stare

Listarea directorului depozitului în HDFS confirmă rezultatul pasului 6 – shell-ul raportează 38 de articole, unul parte_stare/stare= director per stat.

Listare HDFS care afișează 38 de directoare de partiții state_part în depozitul Hive

Din codul de mai sus, facem următoarele lucruri

  1. Crearea tabelului allstates cu 3 nume de coloane, cum ar fi stat, district și înscrieri
  2. Încărcarea datelor în tabelul allstates
  3. Crearea tabelului de partiții cu stare ca cheie de partiție
  4. În acest pas, setarea modului de partiție ca nestrict (acest mod va activa modul de partiție dinamică)
  5. Încărcarea datelor în tabela de partiții state_part
  6. Procesarea efectivă și formarea tabelelor de partiții pe baza stării ca cheie de partiție
  7. Vor exista 38 de ieșiri de partiție în spațiul de stocare HDFS, cu numele fișierului ca nume de stare. În acest pas, vedem cele 38 de ieșiri de partiție în HDFS.

Partiționare statică vs. dinamică în Hive

Exemplul de mai sus folosește partiționare dinamică, dar Hive acceptă două stiluri de încărcare, iar diferența decide cât de mult va fi încărcat.ping – și cât de mult risc – prezintă fiecare încărcătură.

Partiționare statică denumește valoarea partiției în instrucțiunea însăși, deci valoarea trebuie cunoscută înainte de rularea încărcării și o instrucțiune umple exact o partiție. Partiționare dinamică permite lui Hive să citească valoarea partiției din ultima coloană a listei SELECT și să creeze directoarele la momentul execuției, motiv pentru care exemplul are nevoie de o singură comandă INSERT pentru a produce 38 de directoare.

Aspect Partiționare statică Partiționare dinamică
Valoarea partiției Furnizat manual în clauza PARTITION Citire la momentul execuției din coloana SELECT
Partiții per instrucțiune O Multe
Configuraţie Funcționează în modul strict implicit Necesită ca hive.exec.dynamic.partition.mode să fie setat la nonstrict
Viteza de încărcare Mai rapid, deoarece nu este necesară scanarea valorilor Mai lent, deoarece jobul grupează rândurile după cheie
Cel mai potrivit pentru Seturi mici, cunoscute, cum ar fi o încărcătură zilnică Seturi de chei mari sau necunoscute, cum ar fi 38 de stări

Încărcările dinamice sunt, de asemenea, limitate. Hive limitează numărul de partiții pe care le poate crea un job – implicit 100 per mapper sau reductor și 1000 pentru întreaga instrucțiune – iar jobul eșuează odată ce se depășește oricare dintre limite, așa că o cheie cu cardinalitate foarte mare necesită creșterea acestor limite sau un design diferit.

Ce este Buckets?

„Bucket-urile” din Hive sunt folosite pentru segregarea datelor din tabelele Hive în mai multe fișiere sau directoare. Sunt folosite pentru interogări eficiente și, spre deosebire de o partiție, numărul de bucket-uri este fix la crearea tabelului, deci nu crește niciodată odată cu datele.

  • Datele prezente în acele partiții pot fi împărțite în continuare în compartimente (bucket-uri).
  • Împărțirea se face pe baza hash-ului anumitor coloane pe care le-am selectat în tabel.
  • Bucket-urile folosesc o formă de algoritm de hashing în back-end pentru a citi fiecare înregistrare și a o plasa în bucket-uri.
  • Găleata în care aterizează un rând este decisă de hash_function(coloană_de_grupare) mod num_grupuri, deci valorile egale ajung întotdeauna în același fișier
  • Pe Hive 0.x și 1.x, gruparea în grupuri trebuia activată cu setează hive.enforce.bucketing=true; înainte de inserție

Ultima setare este istoricul unui cluster curent: manualul Apache Hive notează că nu este necesar începând cu Hive 2.x, deoarece motorul alege acum automat numărul de reduceri și coloana cluster-by din definiția tabelului.

Pas 1) Crearea găleții așa cum se arată mai jos.

Ecranul de mai jos prezintă instrucțiunea CREATE TABLE pentru găleată de probă, cu clauza CLUSTERED BY din partea de jos care fixează numărul de compartimente.

Instrucțiunea Hive CREATE TABLE clusterizează samplebucket-ul în patru compartimente

Din captura de ecran de mai sus

  • Creăm un samplebucket cu nume de coloane precum first_name, job_id, department, salary și country.
  • Creăm 4 găleți aici
  • Odată ce datele sunt încărcate, acestea sunt plasate automat în 4 compartimente.
  • Coloana „țară” este coloana de grupare, deci fiecare rând pentru o țară este scris în același fișier bucket.

Pas 2) Încărcarea datelor în tabelul samplebucket

Presupunând că tabelul „angajați” este deja creat în sistemul Hive, în acest pas vom vedea încărcarea datelor din tabelul angajați în tabelul samplebucket.

Înainte de a începe să mutăm datele angajaților în compartimente (bucket-uri), asigurați-vă că acestea constă din nume de coloane precum first_name, job_id, department, salary și country.

Aici încărcăm date în samplebucket din tabela employees – ecranul de mai jos prezintă instrucțiunea INSERT OVERWRITE care efectuează copierea.

Instrucțiunea INSERT OVERWRITE copiează rândurile angajaților în tabela samplebucket

Pas 3) Afișarea celor 4 găleți create în Pasul 1

Listarea directorului tabel în HDFS arată rezultatul fizic: patru fișiere de date numerotate în loc de unul.

Listarea HDFS a celor patru fișiere bucket create în directorul samplebucket

Din captura de ecran de mai sus, putem vedea că datele din tabelul angajați sunt transferate în cele 4 compartimente create la pasul 1.

Partiționare Hive vs. Bucketing: Diferențe cheie

Ambele caracteristici împart un tabel în bucăți mai mici, dar o fac la niveluri diferite ale sistemului de fișiere și răspund la probleme diferite. Tabelul de mai jos le prezintă una lângă alta.

Punct de comparație partiţionarea găleată
Unitate creată Un director per cheie-valoare Un fișier per bucket hash
Declarat cu ÎMPĂRȚIT DE GRUPATE DE … ÎN n GĂLEȚE
Număr de bucați Crește odată cu numărul de valori distincte Reparat la crearea tabelului
Coloană stocată în fișiere de date Nu – valoarea se află în numele directorului Da – coloana rămâne o coloană normală
Cel mai bun tip de coloană Cardinalitate scăzută, cum ar fi statul, anul sau țara Cardinalitate ridicată, cum ar fi user_id sau transaction_id
Principalul beneficiu Eliminarea partițiilor omite directoarele inutile Dimensiuni uniforme ale fișierelor, eșantionare ieftină și îmbinări pe partea hărții

Cele două nu sunt rivale. Un layout de producție obișnuit partiționează un tabel de fapte după dată și apoi îl grupează în fiecare zi pe cheia de asociere, astfel încât o interogare este redusă la un director și apoi se unește de la un grup la altul în interiorul acestuia.

Când se utilizează partiționarea, gruparea în compartimente sau ambele

Alegerea între ele începe cu cardinalitatea coloanei și forma interogărilor care vor citi tabelul.

  • perete despărțitor când interogările filtrează aproape întotdeauna pe aceeași coloană cu cardinalitate scăzută și când numărul de valori distincte rămâne în sute, nu în milioane
  • Găleată când coloana utilă are prea multe valori distincte pentru a fi un director sau când tabelul este unit sau eșantionat în mod repetat pe acea coloană
  • Folosiți ambele pentru tabele de fapte mari: partiționare la dată, apoi compartimentare în interiorul fiecărei partiții pe cheia de asociere

Modul de eroare la care trebuie să fim atenți este problema fișierelor mici. Partiționarea pe o coloană cu cardinalitate foarte mare – o marcă temporală sau un identificator de client – ​​produce mii de directoare minuscule, fiecare conținând un fișier mult sub dimensiunea blocului HDFS. Acest lucru umflă memoria NameNode și face ca fiecare scanare să fie mai lentă, exact rezultatul pe care partiționarea trebuia să îl prevină. Bucketing-ul evită acest lucru deoarece numărul de fișiere este limitat de definiția tabelului.

Gruparea în clustere (bucketing) are propria sa avertizare: aspectul este corect doar dacă fiecare scriitor îl respectă. Numărul de buzele declarat la creare este metadate, deci un job care scrie în tabel fără a face clustering corect poate lăsa fișiere care nu corespund aspectului declarat, iar eșantionarea sau joncțiunile ulterioare ale buzelor vor citi rândurile greșite.

Întrebări frecvente

Executați SHOW PARTITIONS table_name în shell-ul Hive. Citește metastore-ul și afișează o linie per directorul partiției, ceea ce este mai rapid decât listarea căii depozitului în HDFS și confirmă, de asemenea, că metastore-ul este sincronizat.

ALTER TABLE nume_tabelă ADD PARTITION (state='Goa') înregistrează un director nou, iar ALTER TABLE nume_tabelă DROP PARTITION (state='Goa') îl elimină. Dropping o partiție gestionată își șterge datele, în timp ce abandoneazăping unul extern șterge doar intrarea din metastore.

Hive limitează implicit partițiile dinamice la 100 per nod și 1000 per instrucțiune. O cheie cu mai multe valori distincte depășește limita și oprește jobul. Activează hive.exec.max.dynamic.partitions.pernode și hive.exec.max.dynamic.partitions sau alege o cheie mai grosieră.

Nu. Era necesar pe Hive 0.x și 1.x pentru a forța numărul de reduceri să se potrivească cu numărul de bucket-uri. HIVE-12331 l-a eliminat în Hive 2.0, iar motorul derivă acum atât numărul de reduceri, cât și coloana cluster-by din tabel.

TABLESAMPLE(BUCKET x OUT OF y ON column) citește doar fișierele bucket corespunzătoare, în loc să scaneze totul. Deoarece rândurile au fost indexate prin hashing pe aceeași coloană în momentul scrierii, eșantionul este repetabil și mult mai ieftin decât un filtru de rânduri aleatoriu.

Împărțirea unui tabel în mii de fișiere minuscule irosește memoria NameNode și pornește câte o sarcină per fișier, astfel încât scanările încetinesc. De obicei, aceasta urmează o cheie de partiție cu cardinalitate foarte mare. Cheile mai grosiere, compactarea fișierelor sau segmentarea în clustere rezolvă problema.

Da. Analiza jurnalelor de interogări și modelele de învățare automată din instrumente precum Cloudera Workload XM clasifică coloanele după frecvența de filtrare, asimetrie și cardinalitate, apoi sugerează un aspect. Sugestia trebuie încă revizuită, deoarece nu poate vedea sarcinile de lucru planificate.

Copilot redactează rapid instrucțiunile PARTITIONED BY și CLUSTERED BY dintr-un comentariu, iar asistenții agenți pot genera un script de încărcare complet. Verificați întotdeauna numărul de bucket-uri generate și cheia în raport cu cardinalitatea reală, deoarece modelul ghicește doar pe baza numelor.

Rezumați această postare cu: