Hive skillevægge og spande med eksempel

⚡ Smart opsummering

Partitioner og buckets er de to måder, Apache Hive opdeler tabeldata på disken: en partition opretter én mappe pr. nøgleværdi, mens en bucket hashes rækker til et fast antal filer.

  • 🗂️ Partitionen er en mappe: Hver distinkt værdi i partitionsnøglen bliver sin egen undermappe under tabelmappen i HDFS.
  • ✂️ Beskæring af skillevæg: En forespørgsel, der filtrerer på partitionsnøglen, læser kun de matchende mapper i stedet for at scanne hele tabellen.
  • 🇧🇷 Dynamisk tilstand kræves: Indlæsning af mange partitioner fra en SELECT kræver, at hive.exec.dynamic.partition.mode er indstillet til nonstrict.
  • 🧮 Bucket er en fil: CLUSTERED BY hashes den valgte kolonne og skriver hver række til en af ​​et fast antal filer.
  • 🔍 Prøveudtagning og sammenføjninger: Bucket-tabeller understøtter effektive TABLESAMPLE-læsninger og bucket-joins på kortsiden, hvilket almindelige tabeller ikke kan.
  • 📐 Vælg efter kardinalitet: Partitioner på kolonner med lav kardinalitet, f.eks. status eller dato, og inddel kolonner med høj kardinalitet, f.eks. bruger-id'er.

Hive-partitioner og buckets forklaret med et eksempel

Tabeller, partitioner og buckets er delene af Hive-datamodellering. En tabel definerer skemaet, en partition opdeler tabellen i mapper på disken, og en bucket opdeler dataene i en mappe i et fast antal filer.

Hvad er partitioner?

Hive-partitioner er en måde at organisere tabeller i partitioner ved at opdele tabeller i forskellige dele baseret på partitionsnøgler. Fysisk set er hver partition en separat undermappe under tabelmappen i HDFS, hvilket gør det muligt for Hive at springe data over, den ikke har brug for.

Partitionering er nyttigt, når tabellen har en eller flere partitionsnøgler. Partitionsnøgler er grundlæggende elementer til at bestemme, hvordan dataene gemmes i tabellen. En partitionsnøgle gemmes ikke i selve datafilerne – dens værdi er kodet i mappenavnet, så en forespørgsel, der filtrerer på den nøgle, kan kassere hele mapper, før en række læses. Dette kaldes partitionsbeskæring.

For eksempel: –

"Klienten har e-handelsdata, der tilhører indiske operationer, hvor hver statsoperation (38 stater) nævnes som en helhed. Hvis vi tager statskolonnen som partitionsnøgle og udfører partitioner på disse indiske data som helhed, kan vi få antallet af partitioner (38 partitioner), hvilket er lig med antallet af stater (38), der er til stede i Indien. Således at hver statsdata kan ses separat i partitionstabeller."

Prøve Code Snippet til partitioner

De seks nedenstående sætninger kører i rækkefølge i Hive-shellen. Hver af dem er et separat trin, og de følgende skærmbilleder viser den samme sekvens, der udføres på en live-klynge.

  1. Oprettelse af tabellen allstates
    create table allstates(state string, District string,Enrolments string)
    
    row format delimited
    
    fields terminated by ',';
    
  2. Indlæser data i den oprettede tabel allstates
    Load data local inpath '/home/hduser/Desktop/AllStates.csv' into table allstates;
  3. Oprettelse af partitionstabel
    create table state_part(District string,Enrolments string) PARTITIONED BY(state string);
  4. Til partition skal vi indstille denne egenskab
    set hive.exec.dynamic.partition.mode=nonstrict
  5. Indlæser data i partitionstabel
    INSERT OVERWRITE TABLE state_part PARTITION(state)
    SELECT district,enrolments,state from  allstates;
  6. Faktisk behandling og dannelse af partitionstabeller baseret på tilstand som partitionsnøgle

Der vil være 38 partitionsoutput i HDFS-lageret med filnavnet som tilstandsnavn. Vi vil kontrollere dette i dette trin.

De følgende skærmbilleder viser udførelsen af ​​ovennævnte kode.

På det første skærmbillede kører trin 1 ved bistade> prompt og skaber alle stater tabel med dens tre kolonner og et komma som feltafgrænser.

Hive-shell opretter allstates-tabellen med tre afgrænsede kolonner

Det næste skærmbillede dækker trin 2 og 3: AllStates.csv-filen indlæses i alle staterog den partitionerede tabel delstatsdel oprettes med state deklareret som partitionsnøgle.

Indlæsning af AllStates.csv i allstates og oprettelse af den partitionerede tabel state_part

Trin 4 og 5 vises derefter. Dynamisk partitionstilstand er indstillet til ikke-strict, og INSERT OVERWRITE-sætningen starter et MapReduce-job, hvis loglinjer viser, at én partition indlæses for hver tilstandsværdi.

MapReduce-joboutput indlæser én Hive-partition pr. tilstandsværdi

Listning af lagermappen i HDFS bekræfter resultatet af trin 6 – skallen rapporterer 38 elementer, et statsdel/stat= katalog pr. stat.

HDFS-liste, der viser 38 state_part-part-partionsmapper i Hive-lageret

Fra ovenstående kode gør vi følgende ting

  1. Oprettelse af tabel allstates med 3 kolonnenavne såsom stat, distrikt og tilmeldinger
  2. Indlæser data i tabellen allstates
  3. Oprettelse af partitionstabel med tilstand som partitionsnøgle
  4. I dette trin indstilles partitionstilstanden som ikke-streng (denne tilstand aktiverer dynamisk partitionstilstand)
  5. Indlæser data i partitionstabellen state_part
  6. Faktisk behandling og dannelse af partitionstabeller baseret på tilstand som partitionsnøgle
  7. Der vil være 38 partitionsoutput i HDFS-lageret med filnavnet som tilstandsnavn. I dette trin ser vi de 38 partitionsoutput i HDFS.

Statisk vs. dynamisk partitionering i Hive

Det ovenstående eksempel bruger dynamisk partitionering, men Hive understøtter to indlæsningsstile, og forskellen bestemmer, hvor meget typing – og hvor stor risiko – hver last medfører.

Statisk partitionering navngiver partitionsværdien i selve sætningen, så værdien skal være kendt, før indlæsningen kører, og én sætning udfylder præcis én partition. Dynamisk partitionering lader Hive læse partitionsværdien ud af den sidste kolonne på SELECT-listen og oprette mapperne under kørsel, hvilket er grunden til, at eksemplet kun behøver en enkelt INSERT for at producere 38 mapper.

Aspect Statisk partitionering Dynamisk partitionering
Partitionsværdi Leveret manuelt i PARTITION-klausulen Læs ved kørsel fra SELECT-kolonnen
Partitioner pr. sætning Én Mange
Konfiguration Fungerer i standard streng tilstand Skal hive.exec.dynamic.partition.mode indstilles til nonstrict
Indlæsningshastighed Hurtigere, fordi der ikke er behov for værdiscanning Langsommere, fordi jobbet grupperer rækker efter nøgle
Bedst egnet til Små, kendte sæt såsom en daglig belastning Store eller ukendte nøglesæt såsom 38 tilstande

Dynamiske belastninger er også begrænsede. Hive begrænser, hvor mange partitioner ét job kan oprette – som standard 100 pr. mapper eller reducer og 1000 for hele sætningen – og jobbet mislykkes, når et af lofterne overskrides, så en nøgle med meget høj kardinalitet kræver, at disse grænser hæves, eller at der er et andet design.

Hvad er Buckets?

Buckets i Hive bruges til at adskille Hive-tabeldata i flere filer eller mapper. De bruges til effektiv forespørgsel, og i modsætning til en partition er antallet af buckets fast, når tabellen oprettes, så den aldrig vokser med dataene.

  • Dataene, der findes i disse partitioner, kan yderligere opdeles i buckets (sække).
  • Opdelingen udføres baseret på hash af bestemte kolonner, som vi har valgt i tabellen.
  • Buckets bruger en form for hashing-algoritme i backend til at læse hver post og placere den i buckets.
  • Den spand, en række lander i, bestemmes af hash_function(bucketing_column) mod num_buckets, så ens værdier altid lander i den samme fil
  • På Hive 0.x og 1.x skulle bucketing aktiveres med sæt hive.enforce.bucketing=true; før indsættelsen

Den sidste indstilling er historik på en aktuel klynge: Apache Hive-manualen bemærker, at det ikke er nødvendigt fra Hive 2.x og fremefter, fordi motoren nu automatisk vælger reducer-antallet og cluster-by-kolonnen fra tabeldefinitionen.

Trin 1) Oprettelse af spand som vist nedenfor.

Skærmen nedenfor viser CREATE TABLE-sætningen for prøvespand, hvor CLUSTERED BY-klausulen nederst fastsætter antallet af buckets.

Hive CREATE TABLE-sætning, der grupperer samplebucket i fire buckets

Fra ovenstående skærmbillede

  • Vi opretter samplebucket med kolonnenavne som fornavn, job-id, afdeling, løn og land.
  • Vi laver 4 spande herovre
  • Når dataene er indlæst, placeres de automatisk i 4 buckets.
  • Landekolonnen er klyngekolonnen, så hver række for ét land skrives til den samme bucket-fil

Trin 2) Indlæser data i tabellen samplebucket

Hvis vi antager, at tabellen "medarbejdere" allerede er oprettet i Hive-systemet, vil vi i dette trin se indlæsningen af ​​data fra tabellen "medarbejdere" i tabellen "samplebucket".

Før vi begynder at flytte medarbejderdata til buckets, skal vi sørge for, at de består af kolonnenavne som fornavn, job-id, afdeling, løn og land.

Her indlæser vi data i samplebucket fra employeestabellen – skærmbilledet nedenfor viser INSERT OVERWRITE-sætningen, der udfører kopieringen.

INSERT OVERWRITE-sætning kopierer medarbejderrækker ind i samplebucket-tabellen

Trin 3) Visning af de 4 buckets, der blev oprettet i trin 1

Hvis man viser tabelmappen i HDFS, vises det fysiske resultat: fire nummererede datafiler i stedet for én.

HDFS-liste over de fire bucket-filer, der er oprettet under samplebucket-mappen

Fra ovenstående skærmbillede kan vi se, at dataene fra medarbejdertabellen overføres til de 4 buckets, der blev oprettet i trin 1.

Hive-partitionering vs. bucketing: Vigtigste forskelle

Begge funktioner deler en tabel op i mindre dele, men de gør det på forskellige niveauer i filsystemet, og de besvarer forskellige problemer. Tabellen nedenfor viser dem side om side.

Punkt af sammenligning Partitionering Inddeling
Enhed oprettet En mappe pr. nøgleværdi En fil pr. hash-bucket
Erklæret med OPDELT AF KLYNGERET EFTER … I n SPANDE
Antal stykker Vokser med antallet af forskellige værdier Rettelse ved tabeloprettelse
Kolonne gemt i datafiler Nej – værdien findes i mappenavnet Ja – kolonnen forbliver en normal kolonne
Bedste kolonnetype Lav kardinalitet, såsom stat, år eller land Høj kardinalitet, såsom user_id eller transaction_id
Hovedfordel Partitionsbeskæring springer unødvendige mapper over Jævne filstørrelser, billig sampling og joins på kortsiden

De to er ikke rivaler. Et almindeligt produktionslayout opdeler en faktatabel efter dato og bucketer derefter hver dag på join-nøglen, så en forespørgsel beskæres til én mappe og derefter joiner bucket-til-bucket indeni den.

Hvornår skal man bruge partitionering, bucketing eller begge dele

Valget mellem dem starter med kolonnens kardinalitet og formen på de forespørgsler, der læser tabellen.

  • Partition når forespørgsler næsten altid filtrerer på den samme kolonne med lav kardinalitet, og når antallet af forskellige værdier forbliver i hundredvis i stedet for millioner
  • Bucket når den nyttige kolonne har for mange forskellige værdier til at være en mappe, eller når tabellen joines eller samples gentagne gange på den kolonne.
  • Brug begge dele for store faktatabeller: partitionering på datoen, derefter bucket inden for hver partition på join-nøglen

Den fejltilstand, man skal være opmærksom på, er problemet med små filer. Partitionering på en kolonne med meget høj kardinalitet – et tidsstempel eller et kunde-id – producerer tusindvis af små mapper, der hver indeholder en fil langt under HDFS-blokstørrelsen. Det oppuster NameNode-hukommelsen og gør hver scanning langsommere, hvilket er præcis det resultat, partitioneringen var ment til at forhindre. Bucketing undgår dette, fordi filantallet er begrænset af tabeldefinitionen.

Bucketing har sin egen advarsel: layoutet er kun korrekt, hvis alle forfattere overholder det. Det bucket-antal, der er deklareret ved oprettelsen, er metadata, så et job, der skriver til tabellen uden korrekt klyngedannelse, kan efterlade filer, der ikke matcher det deklarerede layout, og senere sampling eller bucket-joins vil læse de forkerte rækker.

Ofte Stillede Spørgsmål

Kør SHOW PARTITIONS table_name i Hive-shellen. Den læser metastoren og udskriver én linje pr. partitionsmappe, hvilket er hurtigere end at angive warehouse-stien i HDFS, og det bekræfter også, at metastoren er synkroniseret.

ALTER TABLE table_name ADD PARTITION (state='Goa') registrerer en ny mappe, og ALTER TABLE table_name DROP PARTITION (state='Goa') fjerner den. Dropping en administreret partition sletter sine data, mens den slipperping en ekstern sletter kun metastore-posten.

Hive begrænser dynamiske partitioner som standard til 100 pr. node og 1000 pr. sætning. En nøgle med mere distinkte værdier overskrider grænsen og afslutter jobbet. Opret hive.exec.max.dynamic.partitions.pernode og hive.exec.max.dynamic.partitions, eller vælg en grovere nøgle.

Nej. Det var nødvendigt på Hive 0.x og 1.x for at tvinge reducer-antallet til at matche bucket-antallet. HIVE-12331 fjernede det i Hive 2.0, og motoren udleder nu både reducer-antallet og cluster-by-kolonnen fra tabellen.

TABLESAMPLE(BUCKET x OUT OF y ON kolonne) læser kun de matchende bucket-filer i stedet for at scanne alt. Fordi rækkerne blev hashet på den samme kolonne på skrivetidspunktet, er eksemplet gentageligt og langt billigere end et filter for tilfældige rækker.

At opdele en tabel i tusindvis af små filer spilder NameNode-hukommelse og starter én opgave pr. fil, så scanninger bliver langsommere. Den følger normalt en partitionsnøgle med meget høj kardinalitet. Grovere nøgler, bucketing eller filkomprimering løser det.

Ja. Forespørgselsloganalyse og maskinlæringsmodeller i værktøjer som Cloudera Workload XM rangerer kolonner efter filterfrekvens, skævhed og kardinalitet og foreslår derefter et layout. Forslaget skal stadig gennemgås, fordi det ikke kan se planlagte arbejdsbelastninger.

Copilot udkaster hurtigt PARTITIONED BY- og CLUSTERED BY-sætninger fra en kommentar, og agentassistenter kan generere et helt indlæsningsscript. Kontroller altid det genererede antal buckets og nøglen mod den reelle kardinalitet, fordi modellen gætter udelukkende ud fra navne.

Opsummer dette indlæg med: