Adaptivní zpracování dotazů
Adaptivní provádění dotazů (AQE) představuje opětovnou optimalizaci dotazů, ke které dochází během provádění dotazů.
Motivací k opětovné optimalizaci modulu runtime je, že Azure Databricks má na konci výměny náhodného a všesměrového vysílání nejaktuálnější statistiku (označovanou jako fáze dotazu v AQE). V důsledku toho může Azure Databricks zvolit lepší fyzickou strategii, vybrat optimální velikost a číslo oddílu po náhodném prohazování nebo provést optimalizace, které se používají k vyžadování tipů, například zpracování nerovnoměrné distribuce spojení.
To může být velmi užitečné, když shromažďování statistik není zapnuté nebo když jsou statistiky zastaralé. Je také užitečná na místech, kde staticky odvozené statistiky nejsou přesné, například uprostřed složitého dotazu nebo po výskytu nerovnoměrné distribuce dat.
Funkce
Funkce AQE je ve výchozím nastavení povolená. Má 4 hlavní funkce:
- Dynamicky se mění sloučení spojení sloučení do spojení hash všesměrových přenosů.
- Dynamicky slučuje oddíly (kombinují malé oddíly do oddílů s rozumnou velikostí) po výměně náhodného prohazování. Velmi malé úlohy mají horší propustnost vstupně-výstupních operací a mají tendenci mít větší nároky na plánování režie a nastavení úloh. Kombinace malých úloh šetří prostředky a zlepšuje propustnost clusteru.
- Dynamicky zpracovává nerovnoměrnou distribuci spojení sloučení řazení a shuffle hash spojení rozdělením (a replikací v případě potřeby) nerovnoměrnou distribuci úkolů do zhruba rovnoměrně velkých úkolů.
- Dynamicky rozpoznává a šíří prázdné relace.
Aplikace
AQE se vztahuje na všechny dotazy, které jsou:
- Bez streamování
- Obsahují aspoň jednu výměnu (obvykle v případě spojení, agregace nebo okna), jednoho dílčího dotazu nebo obojího.
Ne všechny dotazy použité na AQE jsou nutně znovu optimalizované. Opětovná optimalizace může nebo nemusí přijít s jiným plánem dotazu, než je plán dotazu staticky zkompilovaný. Pokud chcete zjistit, jestli plán dotazu AQE změnil, přečtěte si následující část Plány dotazů.
Plány dotazů
Tato část popisuje, jak můžete prozkoumat plány dotazů různými způsoby.
V této části:
Uživatelské rozhraní Sparku
Uzel AdaptiveSparkPlan
Použité dotazy AQE obsahují jeden nebo více AdaptiveSparkPlan
uzlů, obvykle jako kořenový uzel každého hlavního dotazu nebo dílčího dotazu.
Před spuštěním dotazu nebo jeho spuštěním isFinalPlan
se příznak odpovídajícího AdaptiveSparkPlan
uzlu zobrazí jako false
; po dokončení provádění dotazu se isFinalPlan
příznak změní na true.
Vývojový plán
Diagram plánu dotazu se vyvíjí s průběhem provádění a odráží nejaktuálnější plán, který se provádí. Uzly, které už byly spuštěny (ve kterých jsou k dispozici metriky), se nezmění, ale ty, které se v průběhu času nemůžou v důsledku opětovné optimalizace změnit.
Následuje příklad diagramu plánu dotazu:
DataFrame.explain()
Uzel AdaptiveSparkPlan
Použité dotazy AQE obsahují jeden nebo více AdaptiveSparkPlan
uzlů, obvykle jako kořenový uzel každého hlavního dotazu nebo dílčího dotazu. Před spuštěním dotazu nebo při jeho spuštění isFinalPlan
se příznak odpovídajícího AdaptiveSparkPlan
uzlu zobrazí jako false
; po dokončení provádění dotazu se isFinalPlan
příznak změní na true
.
Aktuální a počáteční plán
Pod každým AdaptiveSparkPlan
uzlem bude počáteční plán (plán před použitím optimalizace AQE) i aktuální nebo konečný plán v závislosti na tom, jestli se provádění dokončilo. Aktuální plán se bude vyvíjet v průběhu provádění.
Statistika modulu runtime
Každá fáze náhodného prohazování a všesměrového vysílání obsahuje statistiky dat.
Před spuštěním fáze nebo při spuštění fáze jsou statistiky odhady času kompilace a příznak isRuntime
je false
například: Statistics(sizeInBytes=1024.0 KiB, rowCount=4, isRuntime=false);
Po dokončení provádění fáze se statistiky shromažďují za běhu a příznak isRuntime
se stane true
například: Statistics(sizeInBytes=658.1 KiB, rowCount=2.81E+4, isRuntime=true)
DataFrame.explain
Následuje příklad:
Před provedením
Během provádění
Po provedení
SQL EXPLAIN
Uzel AdaptiveSparkPlan
Použité dotazy AQE obsahují jeden nebo více uzlů AdaptiveSparkPlan, obvykle jako kořenový uzel každého hlavního dotazu nebo dílčího dotazu.
Žádný aktuální plán
Vzhledem k tomu SQL EXPLAIN
, že dotaz nespustí, aktuální plán je vždy stejný jako počáteční plán a neodráží, co by nakonec provedl AQE.
Následuje příklad vysvětlení SQL:
Účinnost
Plán dotazu se změní, pokud se projeví jedna nebo více optimalizací AQE. Účinek těchto optimalizací AQE je demonstrován rozdílem mezi aktuálními a konečnými plány a počátečním plánem a konkrétními uzly plánu v aktuálních a konečných plánech.
Dynamická změna sloučení spojení sloučení do spojení hash všesměrového vysílání: různé fyzické spojovací uzly mezi aktuálním/konečným plánem a počátečním plánem
Dynamicky shodovat oddíly: uzel
CustomShuffleReader
s vlastnostíCoalesced
Dynamicky zpracovává nerovnoměrné spojení: uzel
SortMergeJoin
s polemisSkew
jako true.Dynamicky rozpozná a šíří prázdné relace: část (nebo celý) plán se nahradí uzlem LocalTableScan s relačním polem jako prázdné.
Konfigurace
V této části:
- Povolení a zakázání adaptivního spouštění dotazů
- Povolení automatického náhodného náhodného prohazu
- Dynamická změna spojení sloučení sloučení do spojení hash všesměrových přenosů
- Dynamicky slučovat oddíly
- Dynamické zpracování nerovnoměrné distribuce spojení
- Dynamické zjišťování a šíření prázdných relací
Povolení a zakázání adaptivního spouštění dotazů
Vlastnost |
---|
spark.databricks.optimizer.adaptive.enabled Typ: Boolean Určuje, jestli chcete povolit nebo zakázat adaptivní spouštění dotazů. Výchozí hodnota: true |
Povolení automatického náhodného náhodného prohazu
Vlastnost |
---|
spark.sql.shuffle.partitions Typ: Integer Výchozí počet oddílů, které se mají použít při náhodném prohazování dat pro spojení nebo agregace. Nastavení hodnoty auto umožňuje automaticky optimalizované náhodné prohazování, které automaticky určuje toto číslo na základě plánu dotazu a velikosti vstupních dat dotazu.Poznámka: U strukturovaného streamování nelze tuto konfiguraci změnit mezi restartováními dotazů ze stejného umístění kontrolního bodu. Výchozí hodnota: 200 |
Dynamická změna spojení sloučení sloučení do spojení hash všesměrových přenosů
Vlastnost |
---|
spark.databricks.adaptive.autoBroadcastJoinThreshold Typ: Byte String Prahová hodnota pro aktivaci přepnutí na všesměrové připojení za běhu. Výchozí hodnota: 30MB |
Dynamicky slučovat oddíly
Vlastnost |
---|
spark.sql.adaptive.coalescePartitions.enabled Typ: Boolean Určuje, jestli chcete povolit nebo zakázat rozdělení oddílů. Výchozí hodnota: true |
spark.sql.adaptive.advisoryPartitionSizeInBytes Typ: Byte String Cílová velikost po zvětšování. Sloučené velikosti oddílů se budou blížit, ale nebudou větší než tato cílová velikost. Výchozí hodnota: 64MB |
spark.sql.adaptive.coalescePartitions.minPartitionSize Typ: Byte String Minimální velikostoddílůch Sloučené velikosti oddílů nebudou menší než tato velikost. Výchozí hodnota: 1MB |
spark.sql.adaptive.coalescePartitions.minPartitionNum Typ: Integer Minimální počet oddílů po součtení. Nedoporučuje se, protože nastavení explicitně přepisuje spark.sql.adaptive.coalescePartitions.minPartitionSize .Výchozí hodnota: 2x ne. jader clusteru |
Dynamické zpracování nerovnoměrné distribuce spojení
Vlastnost |
---|
spark.sql.adaptive.skewJoin.enabled Typ: Boolean Jestli chcete povolit nebo zakázat zpracování nerovnoměrné distribuce spojení. Výchozí hodnota: true |
spark.sql.adaptive.skewJoin.skewedPartitionFactor Typ: Integer Faktor, který při vynásobení velikostí mediánu oddílů přispívá k určení, zda je oddíl nerovnoměrně zkosený. Výchozí hodnota: 5 |
spark.sql.adaptive.skewJoin.skewedPartitionThresholdInBytes Typ: Byte String Prahová hodnota, která přispívá k určení, jestli je oddíl nerovnoměrný. Výchozí hodnota: 256MB |
Oddíl se považuje za nerovnoměrnou distribuci, pokud jsou oba (partition size > skewedPartitionFactor * median partition size)
a (partition size > skewedPartitionThresholdInBytes)
jsou true
.
Dynamické zjišťování a šíření prázdných relací
Vlastnost |
---|
spark.databricks.adaptive.emptyRelationPropagation.enabled Typ: Boolean Určuje, jestli chcete povolit nebo zakázat šíření dynamické prázdné relace. Výchozí hodnota: true |
Nejčastější dotazy
V této části:
- Proč AQE nevysílala malou tabulku spojení?
- Mám stále používat nápovědu ke strategii připojení k vysílání s povolenou funkcí AQE?
- Jaký je rozdíl mezi nápovědou ke zkosení spojení a optimalizací spojení nerovnoměrné distribuce AQE? Který z nich mám použít?
- Proč AQE automaticky neupravoval pořadí připojení?
- Proč AQE nerozpoznal nerovnoměrnou distribuci dat?
Proč AQE nevysílala malou tabulku spojení?
Pokud velikost relace očekávaného vysílání spadá pod tuto prahovou hodnotu, ale stále není všesměrové:
- Zkontrolujte typ spojení. Vysílání není podporováno pro určité typy spojení, například levý vztah
LEFT OUTER JOIN
nelze vysílat. - Může to být také to, že relace obsahuje velké množství prázdných oddílů, v takovém případě může většina úkolů rychle dokončit spojení se sloučením řazení nebo může být optimalizována pomocí zpracování nerovnoměrné spojení spojení. AQE zabraňuje změně takových spojení sloučení řazení na všesměrové spojení hash, pokud je procento neprázdných oddílů nižší než
spark.sql.adaptive.nonEmptyPartitionRatioForBroadcastJoin
.
Mám stále používat nápovědu ke strategii připojení k vysílání s povolenou funkcí AQE?
Ano. Staticky plánované spojení všesměrového vysílání je obvykle výkonnější než dynamicky plánované AQE jako AQE nemusí přepnout na všesměrové spojení, dokud se nepromíchá pro obě strany spojení (čas, kdy jsou získány skutečné velikosti relací). Pokud tedy znáte svůj dotaz dobře, může být použití nápovědy vysílání stále dobrou volbou. AQE bude respektovat rady dotazů stejným způsobem jako statická optimalizace, ale může stále používat dynamické optimalizace, které nejsou ovlivněny radami.
Jaký je rozdíl mezi nápovědou ke zkosení spojení a optimalizací spojení nerovnoměrné distribuce AQE? Který z nich mám použít?
Místo použití nápovědy ke nerovnoměrné distribuci spojení AQE se doporučuje spoléhat na zpracování nerovnoměrného spojení, protože nerovnoměrné spojení AQE je zcela automatické a obecně funguje lépe než protějšek nápovědy.
Proč AQE automaticky neupravoval pořadí připojení?
Změna pořadí dynamického spojení není součástí AQE.
Proč AQE nerozpoznal nerovnoměrnou distribuci dat?
Aby AQE zjistil oddíl jako zkosený oddíl, musí být splněné dvě podmínky velikosti:
- Velikost oddílu
spark.sql.adaptive.skewJoin.skewedPartitionThresholdInBytes
je větší než (výchozí 256 MB) - Velikost oddílu je větší než medián všech oddílů, kolikrát je nerovnoměrný faktor
spark.sql.adaptive.skewJoin.skewedPartitionFactor
oddílu (výchozí 5).
Kromě toho je podpora zpracování nerovnoměrné distribuce omezena pro určité typy spojení, například v LEFT OUTER JOIN
, lze optimalizovat pouze nerovnoměrnou distribuci na levé straně.
Starší verze
Pojem Adaptivní spouštění existoval od Sparku 1.6, ale nový AQE ve Sparku 3.0 se zásadně liší. Z hlediska funkčnosti Spark 1.6 pouze část "dynamicky slučuje oddíly". Z hlediska technické architektury je nová architektura AQE architekturou dynamického plánování a opětovného plánování dotazů na základě statistik modulu runtime, která podporuje řadu optimalizací, jako jsou ty, které jsme popsali v tomto článku, a lze je rozšířit, aby bylo možné optimalizovat více potenciálních optimalizací.