Přepážky úlů a lopaty s příkladem

⚡ Chytré shrnutí

Oddíly a kontejnery jsou dva způsoby, jakými Apache Hive rozděluje data tabulek na disku: oddíl vytváří jeden adresář na hodnotu klíče, zatímco kontejner hašuje řádky do pevného počtu souborů.

  • 🗂️ Oddíl je adresář: Každá odlišná hodnota klíče oddílu se stane vlastním podadresářem ve složce tabulky v systému HDFS.
  • ✂️ Prořezávání příček: Dotaz, který filtruje podle klíče oddílu, čte pouze odpovídající adresáře místo prohledávání celé tabulky.
  • ⚙️ Požadovaný dynamický režim: Načítání mnoha oddílů z příkazu SELECT vyžaduje nastavení hive.exec.dynamic.partition.mode na nonstrict.
  • 🧮 Bucket je soubor: Funkce CLUSTERED BY hašuje vybraný sloupec a zapisuje každý řádek do jednoho z pevně stanoveného počtu souborů.
  • 🔍 Vzorkování a spojení: Bucketované tabulky podporují efektivní čtení TABLESAMPLE a spojení bucketů na straně mapy, což prosté tabulky nemohou.
  • 📐 Vyberte podle mohutnosti: Rozdělte na sloupce s nízkou mohutností, jako je stav nebo datum, a na sloupce s vysokou mohutností, jako jsou identifikátory uživatelů.

Vysvětlení oddílů a kbelíků úlu s pomocí praktického příkladu

Tabulky, oddíly a kontejnery jsou součástí modelování dat Hive. Tabulka definuje schéma, oddíl rozděluje tuto tabulku do adresářů na disku a kontejner rozděluje data uvnitř adresáře do pevně stanoveného počtu souborů.

Co je to oddíly?

Hive Partitions je způsob, jak uspořádat tabulky do oddílů rozdělením tabulek na různé části na základě klíčů oddílů. Fyzicky je každý oddíl samostatným podadresářem ve složce tabulky v HDFS, což umožňuje Hive přeskočit data, která nepotřebuje.

Rozdělení je užitečné, pokud tabulka obsahuje jeden nebo více klíčů oddílu. Klíče oddílu jsou základní prvky pro určení, jak jsou data uložena v tabulce. Klíč oddílu není uložen uvnitř samotných datových souborů – jeho hodnota je zakódována v názvu adresáře, takže dotaz filtrující tento klíč může zahodit celé adresáře před přečtením jakéhokoli řádku. Tomu se říká prořezávání oddílů.

Například: –

„Klient má data elektronického obchodování, která patří k operacím v Indii, ve kterých jsou všechny operace ve státě (38 států) uvedeny jako celek. Pokud vezmeme sloupec státu jako klíč oddílu a provedeme rozdělení na tato data v Indii jako celek, můžeme získat počet oddílů (38 oddílů), který se rovná počtu států (38) přítomných v Indii. Data každého státu lze tedy zobrazit samostatně v tabulkách oddílů.“

Vzorek Code Úryvek pro oddíly

Šest níže uvedených příkazů se v shellu Hive spustí postupně. Každý z nich představuje samostatný krok a následující snímky obrazovky ukazují stejnou sekvenci spouštěnou na aktivním clusteru.

  1. Vytvoření tabulky allstates
    create table allstates(state string, District string,Enrolments string)
    
    row format delimited
    
    fields terminated by ',';
    
  2. Načítání dat do vytvořené tabulky allstates
    Load data local inpath '/home/hduser/Desktop/AllStates.csv' into table allstates;
  3. Vytvoření tabulky oddílů
    create table state_part(District string,Enrolments string) PARTITIONED BY(state string);
  4. Pro oddíl musíme tuto vlastnost nastavit
    set hive.exec.dynamic.partition.mode=nonstrict
  5. Načítání dat do tabulky oddílů
    INSERT OVERWRITE TABLE state_part PARTITION(state)
    SELECT district,enrolments,state from  allstates;
  6. Aktuální zpracování a tvorba tabulek oddílů na základě stavu jako klíč oddílu

V úložišti HDFS bude 38 výstupů oddílů s názvem souboru jako názvem stavu. V tomto kroku to ověříme.

Následující snímky obrazovky ukazují provedení výše uvedeného kódu.

Na první obrazovce probíhá krok 1 na úl> výzvu a vytvoří všechny státy tabulka se třemi sloupci a čárkou jako oddělovačem polí.

Hive shell vytváří tabulku allstates se třemi oddělenými sloupci

Následující obrazovka zahrnuje kroky 2 a 3: soubor AllStates.csv se načte do všechny státya rozdělená tabulka část_stavu je vytvořen se stavem deklarovaným jako klíčem oddílu.

Načtení souboru AllStates.csv do allstates a vytvoření rozdělené tabulky state_part

Dále se zobrazí kroky 4 a 5. Režim dynamického oddílu je nastaven na nestriktní a příkaz INSERT OVERWRITE spustí úlohu MapReduce, jejíž řádky protokolu ukazují, že pro každou hodnotu stavu je načten jeden oddíl.

Výstup úlohy MapReduce načítá jeden oddíl Hive na hodnotu stavu

Výpis adresáře skladu v HDFS potvrzuje výsledek kroku 6 – shell hlásí 38 položek, jednu část_stavu/stav= adresář pro každý stát.

Výpis HDFS zobrazující 38 adresářů oddílů state_part ve skladu Hive

Z výše uvedeného kódu děláme následující věci

  1. Vytvoření tabulky allstates se 3 názvy sloupců, jako například stát, okres a počet studentů
  2. Načítání dat do tabulky allstates
  3. Vytvoření tabulky oddílů se stavem jako klíč oddílu
  4. V tomto kroku nastavte režim oddílů jako nestriktní (tento režim aktivuje dynamický režim oddílů)
  5. Načítání dat do tabulky oddílů state_part
  6. Aktuální zpracování a tvorba tabulek oddílů na základě stavu jako klíč oddílu
  7. V úložišti HDFS bude 38 výstupů oddílů s názvem souboru jako názvem stavu. V tomto kroku vidíme 38 výstupů oddílů v HDFS.

Statické vs. dynamické dělení v Hive

Výše uvedený příklad používá dynamické dělení, ale Hive podporuje dva styly načítání a rozdíl určuje, kolik typing – a kolik rizika – každý náklad nese.

Statické dělení pojmenuje hodnotu oddílu v samotném příkazu, takže hodnota musí být známá před spuštěním načítání a jeden příkaz vyplní přesně jeden oddíl. Dynamické dělení umožňuje Hive přečíst hodnotu oddílu z posledního sloupce seznamu SELECT a vytvořit adresáře za běhu, což je důvod, proč tento příklad potřebuje pouze jeden INSERT k vytvoření 38 adresářů.

Vzhled Statické dělení Dynamické dělení
Hodnota oddílu Ručně dodáváno v klauzuli PARTITION Čtení za běhu ze sloupce SELECT
Oddíly na příkaz Jedna Mnoho
Konfigurace Funguje ve výchozím striktním režimu Vyžaduje nastavení hive.exec.dynamic.partition.mode na nonstrict.
Rychlost načítání Rychlejší, protože není potřeba skenování hodnot Pomalejší, protože úloha seskupuje řádky podle klíče
Nejlépe se hodí Malé, známé sady, jako například denní zátěž Velké nebo neznámé sady klíčů, například 38 států

Dynamické zátěže jsou také omezeny. Hive omezuje počet oddílů, které může jedna úloha vytvořit – ve výchozím nastavení 100 na mapper nebo reducer a 1000 pro celý příkaz – a úloha selže, jakmile je překročen kterýkoli z těchto stropů, takže klíč s velmi vysokou mohutností potřebuje tyto limity zvýšit nebo jiný návrh.

Co je Buckets?

Buckety v Hive se používají k rozdělení dat tabulek Hive do více souborů nebo adresářů. Používají se pro efektivní dotazování a na rozdíl od oddílu je počet bucketů při vytváření tabulky pevně stanovený, takže nikdy neroste s daty.

  • Data, která se nacházejí v těchto oddílech, lze dále rozdělit do segmentů (bucketů).
  • Dělení se provádí na základě hashu konkrétních sloupců, které jsme v tabulce vybrali.
  • Buckety používají na backendu nějaký hashovací algoritmus pro čtení každého záznamu a jeho umístění do bucketů.
  • Do kterého segmentu řádek skončí, určuje hash_function(bucketing_column) mod num_buckets, takže stejné hodnoty se vždy dostanou do stejného souboru
  • V Hive 0.x a 1.x muselo být bucketování povoleno pomocí nastavit hive.enforce.bucketing=true; před vložením

Toto poslední nastavení je historie na aktuálním clusteru: manuál k Apache Hive Poznamenává, že od verze Hive 2.x to není potřeba, protože engine nyní automaticky vybírá počet reduktorů a sloupec cluster-by z definice tabulky.

Krok 1) Vytvoření bucketu, jak je znázorněno níže.

Níže uvedená obrazovka zobrazuje příkaz CREATE TABLE pro vzorkovací kbelík, s klauzulí CLUSTERED BY ve spodní části, která opravuje počet segmentů.

Příkaz Hive CREATE TABLE shlukuje vzorky do čtyř kontejnerů

Z výše uvedeného snímku obrazovky

  • Vytváříme vzorkovací bucket s názvy sloupců, jako je křestní_jméno, ID_pracovní_pozice, oddělení, plat a země.
  • Vytváříme zde 4 kbelíky
  • Jakmile se data načtou, automaticky se umístí do 4 složek.
  • Sloupec země je sloupcem shlukování, takže každý řádek pro jednu zemi je zapsán do stejného souboru bucket.

Krok 2) Načítání dat do tabulky samplebucket

Za předpokladu, že tabulka „employees“ je v systému Hive již vytvořena, uvidíme v tomto kroku načtení dat z tabulky employees do tabulky samplebucket.

Než začneme přesouvat data zaměstnanců do kontejnerů, ujistěte se, že obsahují názvy sloupců, jako je křestní_jméno, ID_pracovní_pozice, oddělení, plat a země.

Zde načítáme data do samplebucket z tabulky employees – níže uvedená obrazovka ukazuje příkaz INSERT OVERWRITE, který provádí kopírování.

Příkaz INSERT OVERWRITE kopíruje řádky zaměstnanců do tabulky samplebucket

Krok 3) Zobrazení 4 segmentů vytvořených v kroku 1

Výpis adresáře tabulek v HDFS ukazuje fyzický výsledek: čtyři číslované datové soubory místo jednoho.

Seznam čtyř souborů bucket vytvořených v adresáři samplebucket v systému HDFS

Z výše uvedeného snímku obrazovky vidíme, že data z tabulky zaměstnanců jsou přenesena do 4 segmentů vytvořených v kroku 1.

Dělení podregistrů vs. bucketing: Klíčové rozdíly

Obě funkce rozdělují tabulku na menší části, ale dělají to na různých úrovních souborového systému a řeší různé problémy. Níže uvedená tabulka je srovnává.

Bod srovnání Rozdělení Nakládání
Jednotka vytvořena Adresář na hodnotu klíče Soubor na hašovací bucket
Deklarováno s ROZDĚLENO PODLE SKLUSTROVÁNO … DO n KOLÍKŮ
Počet kusů Roste s počtem odlišných hodnot Opraveno při vytváření tabulky
Sloupec uložený v datových souborech Ne – hodnota se nachází v názvu adresáře. Ano – sloupec zůstane normálním sloupcem
Nejlepší typ sloupce Nízká mohutnost, například stát, rok nebo země Vysoká kardinalita, například user_id nebo transaction_id
Hlavní přínos Prořezávání oddílů přeskakuje nepotřebné adresáře Rovnoměrné velikosti souborů, levné vzorkování a spojení na straně mapy

Tyto dva typy adresářů nejsou rivaly. Běžné produkční rozvržení rozděluje faktickou tabulku podle data a poté každý den na základě klíče spojení zařazuje do segmentů, takže dotaz se přesune do jednoho adresáře a poté se v něm spojí do segmentů.

Kdy použít dělení, bucketing nebo obojí

Výběr mezi nimi začíná mohutností sloupce a tvarem dotazů, které budou tabulku číst.

  • Rozdělení když dotazy téměř vždy filtrují stejný sloupec s nízkou mohutností a když počet odlišných hodnot zůstává ve stovkách, nikoli v milionech
  • Vědro když má užitečný sloupec příliš mnoho odlišných hodnot na to, aby mohl být adresářem, nebo když je tabulka v daném sloupci opakovaně spojována nebo vzorkována
  • Použijte obě pro velké tabulky faktů: rozdělení na oddíl podle data a poté bucket uvnitř každého oddílu na klíči spojení

Režim selhání, na který je třeba dávat pozor, je problém malých souborů. Dělení na sloupci s velmi vysokou mohutností – časovým razítkem nebo identifikátorem zákazníka – vytváří tisíce malých adresářů, z nichž každý obsahuje soubor hluboko pod velikostí bloku HDFS. To nafukuje paměť NameNode a zpomaluje každé skenování, což je přesně ten výsledek, kterému mělo dělení zabránit. Bucketing se tomu vyhýbá, protože počet souborů je omezen definicí tabulky.

Bucketing má svou výhradu: rozvržení je správné pouze tehdy, pokud ho dodržují všichni zapisovači. Počet bucketů deklarovaný při vytváření jsou metadata, takže úloha, která zapisuje do tabulky bez správného shlukování, může zanechat soubory, které neodpovídají deklarovanému rozvržení, a pozdější vzorkování nebo spojení bucketů přečtou nesprávné řádky.

Nejčastější dotazy

Spusťte v shellu Hive příkaz SHOW PARTITIONS table_name. Přečte metaúložiště a vypíše jeden řádek na adresář oddílu, což je rychlejší než vypsání cesty k úložišti v HDFS a také potvrdí, že je metaúložiště synchronizované.

Příkaz ALTER TABLE table_name ADD PARTITION (state='Goa') zaregistruje nový adresář a příkaz ALTER TABLE table_name DROP PARTITION (state='Goa') jej odstraní. Dropping spravovaný oddíl smaže svá data, zatímco dropping Externí pouze vymaže položku v metaúložišti.

Hive standardně omezuje počet dynamických oddílů na 100 na uzel a 1000 na příkaz. Klíč s více odlišnými hodnotami překročí limit a ukončí úlohu. Zvyšte hodnotu hive.exec.max.dynamic.partitions.pernode a hive.exec.max.dynamic.partitions nebo vyberte klíč s hrubším nastavením.

Ne. V Hive 0.x a 1.x to bylo potřeba k vynucení souladu počtu reduktorů s počtem bucketů. HIVE-12331 to v Hive 2.0 odstranil a engine nyní odvozuje z tabulky jak počet reduktorů, tak sloupec podle clusterů.

Funkce TABLESAMPLE(BUCKET x OUT OF y ON column) čte pouze odpovídající soubory s danými sloupci, místo aby prohledávala všechny sloupce. Protože řádky byly v době zápisu hašovány ve stejném sloupci, je vzorek opakovatelný a mnohem levnější než filtr náhodných řádků.

Rozdělení tabulky na tisíce malých souborů plýtvá pamětí NameNode a spouští jednu úlohu na soubor, takže skenování se zpomaluje. Obvykle následuje po klíči oddílu s velmi vysokou mohutností. Hrubější klíče, bucketing nebo komprimace souborů to řeší.

Ano. Analýza protokolů dotazů a modely strojového učení v nástrojích, jako je Cloudera Workload XM, seřazují sloupce podle frekvence filtrů, zkosení a mohutnosti a poté navrhují rozvržení. Návrh je stále třeba zkontrolovat, protože nevidí plánované úlohy.

Copilot rychle vytváří příkazy PARTITIONED BY a CLUSTERED BY z komentáře a agenti-asistentové mohou vygenerovat celý skript pro načítání. Vždy zkontrolujte vygenerovaný počet segmentů a klíč oproti skutečné mohutnosti, protože model odhaduje pouze z názvů.

Shrňte tento příspěvek takto: