Hive skillevegger og bøtter med eksempel

⚡ Smart oppsummering

Partisjoner og bøtter er de to måtene Apache Hive deler tabelldata på disk: en partisjon oppretter én katalog per nøkkelverdi, mens en bøtte hasher rader til et fast antall filer.

  • 🗂️ Partisjonen er en katalog: Hver distinkte verdi av partisjonsnøkkelen blir sin egen underkatalog under tabellmappen i HDFS.
  • ✂️ Beskjæring av skillevegg: En spørring som filtrerer på partisjonsnøkkelen leser bare de samsvarende mappene i stedet for å skanne hele tabellen.
  • ⚙️ Dynamisk modus kreves: Lasting av mange partisjoner fra en SELECT krever at hive.exec.dynamic.partition.mode er satt til nonstrict.
  • 🧮 Bøtta er en fil: KLYSTERET AV hasher den valgte kolonnen og skriver hver rad inn i en av et fast antall filer.
  • 🔍 Prøvetaking og sammenføyninger: Bøttetabeller støtter effektive TABLESAMPLE-lesinger og bucket-koblinger på kartsiden som vanlige tabeller ikke kan.
  • 📐 Velg etter kardinalitet: Partisjoner på kolonner med lav kardinalitet, for eksempel status eller dato, og grupper kolonner med høy kardinalitet, for eksempel brukeridentifikatorer.

Hive-partisjoner og -bøtter forklart med et utarbeidet eksempel

Tabeller, partisjoner og bøtter er delene av Hive-datamodellering. En tabell definerer skjemaet, en partisjon deler tabellen inn i kataloger på disken, og en bøtte deler dataene i en katalog inn i et fast antall filer.

Hva er partisjoner?

Hive-partisjoner er en måte å organisere tabeller i partisjoner ved å dele tabeller inn i forskjellige deler basert på partisjonsnøkler. Fysisk sett er hver partisjon en egen underkatalog under tabellmappen i HDFS, noe som gjør at Hive kan hoppe over data den ikke trenger.

Partisjonering er nyttig når tabellen har én eller flere partisjonsnøkler. Partisjonsnøkler er grunnleggende elementer for å bestemme hvordan dataene lagres i tabellen. En partisjonsnøkkel lagres ikke i selve datafilene – verdien er kodet i katalognavnet, så en spørring som filtrerer på den nøkkelen kan forkaste hele kataloger før noen rad leses. Dette kalles partisjonsbeskjæring.

For eksempel: –

«Klienten har e-handelsdata som tilhører indiske operasjoner der hver delstatsoperasjon (38 delstater) er nevnt som en helhet. Hvis vi tar delstatskolonnen som partisjonsnøkkel og utfører partisjoner på disse indiske dataene som en helhet, kan vi få antall partisjoner (38 partisjoner) som er lik antall delstater (38) som finnes i India. Slik at hver delstatsdata kan vises separat i partisjonstabeller.»

Eksempel Code Kodebit for partisjoner

De seks setningene nedenfor kjøres i rekkefølge i Hive-skallet. Hvert trinn er et separat trinn, og skjermbildene som følger viser samme sekvens som kjøres på en live-klynge.

  1. Oppretting av tabellen allstates
    create table allstates(state string, District string,Enrolments string)
    
    row format delimited
    
    fields terminated by ',';
    
  2. Laster inn data i den opprettede tabellen allstates
    Load data local inpath '/home/hduser/Desktop/AllStates.csv' into table allstates;
  3. Oppretting av partisjonstabell
    create table state_part(District string,Enrolments string) PARTITIONED BY(state string);
  4. For partisjon må vi angi denne egenskapen
    set hive.exec.dynamic.partition.mode=nonstrict
  5. Laster data inn i partisjonstabell
    INSERT OVERWRITE TABLE state_part PARTITION(state)
    SELECT district,enrolments,state from  allstates;
  6. Faktisk behandling og dannelse av partisjonstabeller basert på tilstand som partisjonsnøkkel

Det vil være 38 partisjonsutganger i HDFS-lagring med filnavnet som tilstandsnavn. Vi vil sjekke dette i dette trinnet.

Følgende skjermbilder viser utførelsen av koden nevnt ovenfor.

I det første skjermbildet kjører trinn 1 på bikube> spørre og oppretter alle stater tabellen med de tre kolonnene og et komma som feltskilletegn.

Hive-skall oppretter allstates-tabellen med tre avgrensede kolonner

Neste skjermbilde dekker trinn 2 og 3: AllStates.csv-filen lastes inn i alle stater, og den partisjonerte tabellen delstatsdel opprettes med state deklarert som partisjonsnøkkel.

Laster AllStates.csv inn i allstates og oppretter den partisjonerte tabellen state_part

Trinn 4 og 5 vises deretter. Dynamisk partisjonsmodus er satt til ikke-streng, og INSERT OVERWRITE-setningen starter en MapReduce-jobb der logglinjene viser at én partisjon lastes inn for hver tilstandsverdi.

MapReduce-jobputdata laster inn én Hive-partisjon per tilstandsverdi

Oppføring av lagerkatalogen i HDFS bekrefter resultatet av trinn 6 – skallet rapporterer 38 elementer, ett delstatsdel/delstat= katalog per stat.

HDFS-liste som viser 38 state_part-partisjonskataloger i Hive-lageret

Fra koden ovenfor gjør vi følgende ting

  1. Oppretting av tabellen allstates med 3 kolonnenavn som stat, distrikt og påmeldinger
  2. Laster inn data i tabellen allstates
  3. Oppretting av partisjonstabell med tilstand som partisjonsnøkkel
  4. I dette trinnet angir du partisjonsmodus som ikke-streng (denne modusen vil aktivere dynamisk partisjonsmodus)
  5. Laster inn data i partisjonstabellen state_part
  6. Faktisk behandling og dannelse av partisjonstabeller basert på tilstand som partisjonsnøkkel
  7. Det vil være 38 partisjonsutganger i HDFS-lagring med filnavnet som tilstandsnavn. I dette trinnet ser vi de 38 partisjonsutgangene i HDFS.

Statisk vs. dynamisk partisjonering i Hive

Det utarbeidede eksemplet ovenfor bruker dynamisk partisjonering, men Hive støtter to lastestiler, og forskjellen bestemmer hvor mye typing – og hvor mye risiko – hver last medfører.

Statisk partisjonering navngir partisjonsverdien i selve setningen, så verdien må være kjent før innlastingen kjører og én setning fyller nøyaktig én partisjon. Dynamisk partisjonering lar Hive lese partisjonsverdien ut av den siste kolonnen i SELECT-listen og opprette katalogene under kjøring, og det er derfor eksemplet bare trenger én enkelt INSERT for å produsere 38 kataloger.

Aspekt Statisk partisjonering Dynamisk partisjonering
Partisjonsverdi Leveres for hånd i PARTITION-klausulen Les under kjøring fra SELECT-kolonnen
Partisjoner per setning En Mange
Konfigurasjon Fungerer i standard streng modus Krever at hive.exec.dynamic.partition.mode er satt til nonstrict
Last hastighet Raskere, fordi ingen verdiskanning er nødvendig Tregere, fordi jobben grupperer rader etter nøkkel
Passer best til Små, kjente sett som en daglig belastning Store eller ukjente nøkkelsett, for eksempel 38 tilstander

Dynamiske belastninger er også begrenset. Hive begrenser hvor mange partisjoner én jobb kan opprette – som standard 100 per mapper eller reducer og 1000 for hele setningen – og jobben mislykkes når et av takene krysses, så en nøkkel med svært høy kardinalitet trenger at disse grensene heves eller et annet design.

Hva er Bøtter?

Bøtter i Hive brukes til å separere Hive-tabelldata i flere filer eller mapper. De brukes til effektiv spørring, og i motsetning til en partisjon er antallet bøtter fast når tabellen opprettes, slik at den aldri vokser med dataene.

  • Dataene som finnes i disse partisjonene kan deles videre inn i bøtter
  • Delingen utføres basert på hash av bestemte kolonner som vi valgte i tabellen.
  • Bøtter bruker en eller annen form for hashing-algoritme i bakenden for å lese hver post og plassere den i bøtter.
  • Hvilken bøtte en rad lander i bestemmes av hash_function(bucketing_column) mod num_buckets, slik at like verdier alltid havner i samme fil
  • På Hive 0.x og 1.x måtte bucketing aktiveres med sett hive.enforce.bucketing=true; før innsatsen

Den siste innstillingen er historikk på en gjeldende klynge: Apache Hive-manualen bemerker at det ikke er nødvendig fra Hive 2.x og utover, fordi motoren nå automatisk velger reduksjonsantallet og klynge-etter-kolonnen fra tabelldefinisjonen.

Trinn 1) Lage bøtte som vist nedenfor.

Skjermbildet nedenfor viser CREATE TABLE-setningen for prøvebøtte, med CLUSTERED BY-klausulen nederst som fastsetter antall bøtter.

Hive CREATE TABLE-setning som grupperer samplebucket i fire bøtter

Fra skjermbildet ovenfor

  • Vi lager samplebucket med kolonnenavn som fornavn, jobb-id, avdeling, lønn og land.
  • Vi lager fire bøtter her borte
  • Når dataene er lastet inn, plasseres de automatisk i fire bøtter.
  • Landkolonnen er klyngekolonnen, så hver rad for ett land skrives til den samme bucket-filen

Trinn 2) Laster inn data i tabellens eksempelbøtte

Forutsatt at tabellen «ansatte» allerede er opprettet i Hive-systemet, vil vi i dette trinnet se lasting av data fra tabellen «ansatte» til tabellen «samplebucket».

Før vi begynner å flytte ansattes data til bøtter, må vi sørge for at de består av kolonnenavn som fornavn, jobb-id, avdeling, lønn og land.

Her laster vi inn data i samplebucket fra employees-tabellen – skjermbildet nedenfor viser INSERT OVERWRITE-setningen som utfører kopieringen.

INSERT OVERWRITE-setning kopierer ansattes rader inn i samplebucket-tabellen

Trinn 3) Viser de fire bøttene som ble opprettet i trinn 1

Å liste opp tabellkatalogen i HDFS viser det fysiske resultatet: fire nummererte datafiler i stedet for én.

HDFS-liste over de fire bucket-filene som er opprettet under samplebucket-katalogen

Fra skjermbildet ovenfor kan vi se at dataene fra ansatt-tabellen overføres til de fire bøttene som ble opprettet i trinn 1.

Hive-partisjonering vs. bucketing: Viktige forskjeller

Begge funksjonene deler en tabell opp i mindre deler, men de gjør det på forskjellige nivåer i filsystemet og de svarer på forskjellige problemer. Tabellen nedenfor setter dem side om side.

Sammenligningspunkt Oppdeling Inndeling av buckets
Enhet opprettet En katalog per nøkkelverdi En fil per hash-bøtte
Erklært med DELT AV KLUSTERT ETTER … I n BØTTER
Antall stykker Vokser med antallet distinkte verdier Fikset ved tabelloppretting
Kolonne lagret i datafiler Nei – verdien ligger i katalognavnet Ja – kolonnen forblir en vanlig kolonne
Beste kolonnetype Lav kardinalitet, for eksempel stat, år eller land Høy kardinalitet, for eksempel bruker-ID eller transaksjons-ID
Hovedfordel Partisjonsrensing hopper over unødvendige mapper Jevn filstørrelse, billig sampling og sammenføyninger på kartsiden

De to er ikke rivaler. Et vanlig produksjonsoppsett partisjonerer en faktatabell etter dato og deler deretter inn hver dag på join-nøkkelen, slik at en spørring beskjærer til én katalog og deretter kobler sammen bøtte-til-bøtte inni den.

Når du skal bruke partisjonering, bucketing eller begge deler

Valget mellom dem starter med kolonnens kardinalitet og formen på spørringene som skal lese tabellen.

  • Partisjon når spørringer nesten alltid filtrerer på den samme kolonnen med lav kardinalitet, og når antallet distinkte verdier holder seg i hundrevis i stedet for millioner
  • Bucket når den nyttige kolonnen har for mange forskjellige verdier til å være en katalog, eller når tabellen blir koblet sammen eller samplet gjentatte ganger på den kolonnen
  • Bruk begge deler for store faktatabeller: partisjoner på datoen, deretter bucket inni hver partisjon på join-nøkkelen

Feilmodusen man må se etter er problemet med små filer. Partisjonering på en kolonne med svært høy kardinalitet – et tidsstempel eller en kundeidentifikator – produserer tusenvis av bittesmå mapper, som hver inneholder en fil langt under HDFS-blokkstørrelsen. Dette blåser opp NameNode-minnet og gjør hver skanning tregere, noe som er akkurat det resultatet partisjoneringen var ment å forhindre. Bucketing unngår dette fordi filantallet er begrenset av tabelldefinisjonen.

Bucketing har sitt eget forbehold: layouten er bare korrekt hvis alle forfattere overholder den. Bucket-antall som er deklarert ved opprettelse er metadata, så en jobb som skriver til tabellen uten å gruppere riktig kan etterlate filer som ikke samsvarer med den deklarerte layouten, og senere sampling eller bucket-koblinger vil lese feil rader.

Spørsmål og svar

Kjør SHOW PARTITIONS table_name i Hive-skallet. Den leser metalageret og skriver ut én linje per partisjonskatalog, noe som er raskere enn å liste opp lagerbanen i HDFS, og bekrefter også at metalageret er synkronisert.

ALTER TABLE table_name ADD PARTITION (state='Goa') registrerer en ny katalog, og ALTER TABLE table_name DROP PARTITION (state='Goa') fjerner den. Dropping en administrert partisjon sletter dataene sine, mens den slipperping en ekstern sletter bare metastore-oppføringen.

Hive begrenser dynamiske partisjoner til 100 per node og 1000 per setning som standard. En nøkkel med flere distinkte verdier utløser grensen og avslutter jobben. Hev hive.exec.max.dynamic.partitions.pernode og hive.exec.max.dynamic.partitions, eller velg en grovere nøkkel.

Nei. Det var nødvendig på Hive 0.x og 1.x for å tvinge reduksjonsantallet til å samsvare med bøtteantallet. HIVE-12331 fjernet det i Hive 2.0, og motoren utleder nå både reduksjonsantallet og cluster-by-kolonnen fra tabellen.

TABLESAMPLE(BUCKET x OUT OF y ON kolonne) leser bare de samsvarende bøttefilene i stedet for å skanne alt. Fordi rader ble hashet på samme kolonne ved skrivetidspunktet, er utvalget repeterbart og mye billigere enn et filter for tilfeldige rader.

Å dele en tabell inn i tusenvis av bittesmå filer sløser med NameNode-minne og starter én oppgave per fil, slik at skanninger går tregere. Den følger vanligvis en partisjonsnøkkel med veldig høy kardinalitet. Grovere nøkler, bucketing eller filkomprimering fikser det.

Ja. Spørrelogganalyse og maskinlæringsmodeller i verktøy som Cloudera Workload XM rangerer kolonner etter filterfrekvens, skjevhet og kardinalitet, og foreslår deretter et oppsett. Forslaget må fortsatt gjennomgås, fordi det ikke kan se planlagte arbeidsbelastninger.

Copilot utkaster PARTITIONED BY- og CLUSTERED BY-setninger raskt fra en kommentar, og agentassistenter kan generere et helt lasteskript. Sjekk alltid det genererte antall bøtter og nøkkelen mot reell kardinalitet, fordi modellen gjetter kun ut fra navn.

Oppsummer dette innlegget med: