Ausführliche Erläuterung des zugrunde liegenden Ausführungsprozesses von Spark SQL

Inhalt dieses Artikels
1. Apache Spark
2. Die Entwicklung
von Spark SQL 3. Das zugrunde liegende Ausführungsprinzip von Spark SQL
4. Zwei Optimierungen von Catalyst

Die Vollversion von Portal: Spark Knowledge System Zusammenfassung auf Kindermädchenebene, 50.000 Wörter guter Text!

1. Apache-Spark

Apache Spark ist eine einheitliche Analyse-Engine für die groß angelegte Datenverarbeitung, die auf In- Memory-Computing basiert und die Echtzeitleistung der Datenverarbeitung in einer Big-Data-Umgebung verbessert und gleichzeitig eine hohe Fehlertoleranz und Skalierbarkeit gewährleistet , sodass Benutzer Spark einsetzen können in einer großen Anzahl von Auf der Hardware wird ein Cluster gebildet.

Der Spark-Quellcode ist von 40 W Zeilen in 1.x auf jetzt mehr als 100 W Zeilen angewachsen, und mehr als 1400 große Kühe haben Code beigetragen. Der gesamte Quellcode des Spark-Frameworks ist ein riesiges Projekt.

Zweitens die Entwicklungsgeschichte von Spark SQL

Wir wissen, dass Hive SQL auf Hadoop implementiert, was MapReduce-Aufgaben vereinfacht und eine umfangreiche Datenverarbeitung nur durch das Schreiben von SQL durchführen kann, aber Hive hat auch einen fatalen Nachteil, da die unterste Schicht MapReduce für die Berechnung verwendet und die Abfragelatenz hoch ist.

1. Die Geburt des Hais

Also hat Spark Shark in der frühen Version (vor 1.0) gestartet , was ist das? Shark und Hive sind eigentlich eng verwandt. Viele Dinge am Ende von Shark hängen immer noch von Hive ab, aber modifizierte Speicherverwaltung, physikalischer Plan, Ausführung dreier Module, die Die untere Schicht verwendet das speicherbasierte Rechenmodell von Spark, das die Leistung im Vergleich zu Hive um ein Vielfaches bis Hunderte Male verbessert.

Das Problem tritt auf:

  1. Da die Generierung des Shark-Ausführungsplans stark von Hive abhängt, ist es sehr schwierig, neue Optimierungen hinzuzufügen.

  2. Hive ist Parallelität auf Prozessebene und Spark ist Parallelität auf Threadebene, daher sind viele Thread-unsichere Codes in Hive nicht für Spark geeignet.

  3. Aufgrund der oben genannten Probleme unterhält Shark einen Zweig von Hive, der nicht mit der Hauptlinie zusammengeführt werden kann, was es schwierig macht, ihn aufrechtzuerhalten.

  4. Auf dem Spark Summit am 1. Juli 2014 gab Databricks das Ende der Entwicklung von Shark mit Fokus auf Spark SQL bekannt.

2. SparkSQL-DataFrame war geboren

Das Problem lösen:

  1. Spark SQL-Ausführungsplan und -Optimierung werden an den Optimierer Catalyst übergeben;

  2. Ein Satz einfacher SQL-Parser ist integriert, und HQL ist nicht erforderlich;

  3. Außerdem werden DSL-APIs wie DataFrame eingeführt, die vollständig unabhängig von Hive-Komponenten sein können.

Neue Frage :

Für die erste Version von SparkSQL gibt es noch viele Probleme, wie zum Beispiel, dass sie nur die Verwendung von SQL unterstützen kann, nicht gut mit dem imperativen Format kompatibel ist und der Eintrag nicht einheitlich genug ist.

3. SparkSQL-Dataset war geboren

In der Ära 1.6 fügte SparkSQL eine neue API namens Dataset hinzu. Dataset vereinheitlicht und kombiniert die Verwendung von SQL-Zugriff und imperativer API, was einen epochalen Fortschritt darstellt.

In Dataset können Sie Daten einfach mit SQL abfragen und filtern und dann mit der imperativen API explorative Analysen durchführen.

3. Das zugrunde liegende Ausführungsprinzip von Spark SQL

Die zugrunde liegende Architektur von Spark SQL sieht ungefähr wie folgt aus:

Wie Sie sehen, werden die von uns geschriebenen SQL-Anweisungen von einem Optimierer (Catalyst) in RDDs umgewandelt und dem Cluster zur Ausführung übergeben.

Zwischen SQL und RDD, dem Kern von Spark SQL, befindet sich ein Catalyst, ein Abfrageoptimierungs-Framework für die Ausführung von Spark-SQL-Anweisungen, basierend auf der funktionalen Programmierstruktur von Scala.

Wenn wir den Ausführungsprozess von Spark SQL verstehen wollen, ist es sehr wichtig, den Workflow von Catalyst zu verstehen.

Eine SQL-Anweisung generiert ein Programm, das von der Ausführungsmaschine erkannt werden kann, und es ist untrennbar mit den drei Prozessen Parsing (Parser), Optimierung (Optimizer) und Ausführung (Execution) verbunden . Wenn der Catalyst-Optimierer die Plangenerierung und -optimierung durchführt , ist er wie folgt untrennbar mit seinen eigenen internen fünf Komponenten verbunden:

  1. Parser-Modul : parst SparkSql-Strings in einen abstrakten Syntaxbaum/AST.

  2. Analysemodul : Dieses Modul durchläuft den gesamten AST, bindet Datentypen und Funktionen an jeden Knoten auf dem AST und parst dann die Felder in der Datentabelle gemäß dem Metadaten-Informationskatalog.

  3. Optimizer-Modul : Dieses Modul stellt den Kern von Catalyst dar. Es ist hauptsächlich in zwei Optimierungsstrategien unterteilt, RBO und CBO: RBO ist regelbasierte Optimierung und CBO ist kostenbasierte Optimierung .

  4. SparkPlanner-Modul : Der optimierte logische Ausführungsplan OptimizedLogicalPlan ist immer noch logisch und kann vom Spark-System nicht verstanden werden. Zu diesem Zeitpunkt muss der OptimizedLogicalPlan in einen physischen Plan umgewandelt werden .

  5. CostModel-Modul : Wählen Sie den besten physischen Ausführungsplan hauptsächlich basierend auf früheren Leistungsstatistiken. Die Optimierung dieses Prozesses ist CBO (kostenbasierte Optimierung).

Um den gesamten Prozess besser zu verstehen, werden die folgenden einfachen Beispiele erläutert.

Schritt 1. Parser-Phase: Unparsed Logical Plan

Parser bedeutet einfach, dass die SQL-Zeichenfolge einzeln in Token unterteilt und dann gemäß bestimmten semantischen Regeln in einen Syntaxbaum geparst wird. Das Parser-Modul wird derzeit mithilfe der Drittanbieter-Klassenbibliothek ANTLR implementiert , einschließlich der bekannten Hive, Presto, SparkSQL usw., die alle von ANTLR implementiert werden .

Dabei wird beurteilt, ob die SQL-Anweisung der Spezifikation entspricht, zB ob die Schlüsselwörter wie select from where richtig geschrieben sind. Tabellennamen und Tabellenfelder werden an dieser Stelle natürlich nicht geprüft.

Schritt 2. Analysatorphase: Geparster logischer Plan

Der geparste logische Plan hat im Grunde ein Skelett. Zu diesem Zeitpunkt sind grundlegende Metadateninformationen erforderlich, um diese Morpheme auszudrücken. Die wichtigsten Metadateninformationen umfassen hauptsächlich zwei Teile: das Schema der Tabelle und die grundlegenden Funktionsinformationen . Das Schema der Tabelle hauptsächlich enthält das Schema der Tabelle Grundlegende Definition (Spaltenname, Datentyp), Tabellendatenformat (Json, Text), physischer Speicherort der Tabelle usw. Grundlegende Funktionen beziehen sich hauptsächlich auf Klasseninformationen.

ageAnalyzer durchläuft den gesamten Syntaxbaum erneut und führt eine Datentypbindung und Funktionsbindung an jedem Knoten im Baum durch.Beispielsweise wird das Personenmorphem in eine Tabelle geparst, die drei Spalten gemäß den Metadatentabelleninformationen enthält , iddie sein werden als Datentyp analysiert Eine Variable von , die in eine bestimmte Aggregatfunktion aufgelöst wird.namepeople.ageintsum

Dieser Prozess bestimmt, ob der Tabellenname und der Feldname der SQL-Anweisung wirklich in der Metadaten-Datenbank vorhanden sind.

Schritt 3. Optimierungsmodul: Optimierter logischer Plan

Das Optimierungsmodul Optimizer stellt den Kern des gesamten Catalyst dar. Wie oben erwähnt, ist der Optimierer in zwei Typen unterteilt: regelbasierte Optimierung (RBO) und kostenbasierte Optimierung (CBO). Die regelbasierte Optimierungsstrategie ist eigentlich ein Durchlaufen des Syntaxbaums, und der Musterabgleich wird an Knoten durchgeführt, die eine bestimmte Regel erfüllen, und die entsprechende äquivalente Transformation wird durchgeführt. Im Folgenden werden drei allgemeine Regeln beschrieben: Predicate Pushdown , Constant Folding und Column Pruning .

  • Prädikat-Pushdown

Die linke Seite der obigen Abbildung stellt den geparsten Syntaxbaum dar. Die beiden Tabellen im Syntaxbaum werden zuerst erstellt join, und dann wird der age>10Filter verwendet. Der Join-Operator ist ein sehr zeitaufwändiger Operator. Die zeitaufwändige Operation hängt im Allgemeinen von der Größe der beiden an der Verknüpfung beteiligten Tabellen ab. Wenn die Größe der beiden an der Verknüpfung beteiligten Tabellen reduziert werden kann, wird die erforderliche Zeit für die Join-Operator stark reduziert werden.

Prädikat-Pushdown dient dazu, die Filteroperation vor dem Join herunterzudrücken, und wenn der Join später durchgeführt wird, wird die Datenmenge erheblich reduziert und die Join-Zeit wird zwangsläufig reduziert.

  • Konstantes Falten

Ständige Akkumulation ist wie die Berechnung x+(100+80)->x+180, obwohl es eine kleine Änderung ist, aber sie ist von großer Bedeutung. Ohne Optimierung müsste jedes Ergebnis einmal durchgeführt 100+80und dann zum Ergebnis addiert werden. Nach der Optimierung muss der 100+80Vorgang nicht erneut durchgeführt werden.

  • Spaltenbeschneidung

Das Abschneiden von Spaltenwerten bedeutet, dass bei Verwendung einer Tabelle nicht alle ihre Spaltenwerte gescannt werden müssen, sondern nur die benötigten IDs gescannt werden und die nicht benötigten abgeschnitten werden. Einerseits reduziert diese Optimierung den Verbrauch von Netzwerk- und Speicherdaten erheblich und verbessert andererseits die Scan-Effizienz für spaltenbasierte Speicherdatenbanken erheblich.

Schritt 4. SparkPlanner-Modul: In physischen Ausführungsplan konvertieren

Gemäß den obigen Schritten wurde der logische Ausführungsplan optimiert. Der logische Ausführungsplan kann jedoch immer noch nicht ausgeführt werden. Sie sind nur logisch machbar. Tatsächlich weiß Spark nicht, wie dieses Ding ausgeführt werden soll. Join ist beispielsweise ein abstraktes Konzept, was bedeutet, dass zwei Tabellen gemäß derselben ID zusammengeführt werden. Der Logikausführungsplan erklärt jedoch nicht, wie die Zusammenführung zu implementieren ist.

An diesem Punkt ist es notwendig, den logischen Ausführungsplan in einen physischen Ausführungsplan umzuwandeln, d. h. den logisch machbaren Ausführungsplan in einen Plan umzuwandeln, den Spark tatsächlich ausführen kann. Zum Beispiel formuliert Spark für den Join-Operator verschiedene Algorithmus-Strategien für den Operator gemäß verschiedenen Szenarien BroadcastHashJoin, ShuffleHashJoinusw. SortMergejoinDer physische Ausführungsplan besteht eigentlich darin, eine Algorithmus-Implementierung mit dem geringsten Zeitaufwand unter diesen spezifischen Implementierungen auszuwählen. So wählen Sie, das Folgende ist einfach Sagen Sie:

  • Tatsächlich konvertiert SparkPlanner den optimierten logischen Plan, um mehrere physische Pläne zu generieren, die ausgeführt werden können ;

  • Dann berechnet die CBO-Optimierungsstrategie (kostenbasierte Optimierung) die Kosten jedes physischen Plans gemäß dem Kostenmodell und wählt den physischen Plan mit den geringsten Kosten als endgültigen physischen Plan aus.

Die obigen Schritte 2, 3 und 4 werden kombiniert, was der Catalyst-Optimierer ist!

Schritt 5. Führen Sie den physischen Plan aus

Generieren Sie schließlich gemäß dem optimalen physischen Ausführungsplan Java-Bytecode, konvertieren Sie SQL in DAG und arbeiten Sie in Form von RDD.

Zusammenfassung: Flussdiagramm der Gesamtausführung

4. Zwei Optimierungen von Catalyst

Hier fassen wir zwei wichtige Optimierungen des Catalyst-Optimierers zusammen.

1. RBO: Regelbasierte Optimierung

Optimierungspunkte wie: Predicate Pushdown, Column Clipping, Constant Accumulation etc.

  • Prädikat-Pushdown-Fall :

select 
* 
from 
table1 a 
join 
table2 b 
on a.id=b.id 
where a.age>20 and b.cid=1

Die obige Anweisung wird automatisch so optimiert, dass sie wie folgt aussieht:

select 
*
from
(select * from table1 where age>20) a
join
(select * from table2 where cid=1) b
on a.id=b.id 

Das heißt, die Daten werden im Voraus in der Unterabfragephase gefiltert, und die Menge der gemischten Daten in der späteren Verknüpfung wird stark reduziert.

  • Spalten-Clipping-Fall :

select
a.name, a.age, b.cid
from
(select * from table1 where age>20) a
join
(select * from table2 where cid=1) b
on a.id=b.id

Die obige Anweisung wird automatisch so optimiert, dass sie wie folgt aussieht:

select 
a.name, a.age, b.cid
from
(select name, age, id from table1 where age>20) a
join
(select id, cid from table2 where cid=1) b
on a.id=b.id

Es soll die erforderlichen Spalten im Voraus abfragen und andere unnötige Spalten ausschneiden.

  • Ständige Akkumulation :

select 1+1 as id from table1

Die obige Anweisung wird automatisch so optimiert, dass sie wie folgt aussieht:

select 2 as id from table1

Das heißt, es wird 1+1im Voraus berechnet 2und dann jeder Zeile der ID-Spalte zugewiesen, ohne es jedes Mal zu berechnen 1+1.

2. CBO: Kostenbasierte Optimierung

Das heißt, nachdem SparkPlanner mehrere ausführbare physische Pläne für den optimierten logischen Plan generiert hat, wählen die mehreren physischen Ausführungspläne basierend auf dem Kostenmodell den optimalen physischen Plan mit der geringsten Ausführungszeit aus.

Hinweis:

Spark Knowledge System Zusammenfassung auf Nanny-Niveau, 50.000 Wörter guter Text!

{{o.name}}
{{m.name}}

Ich denke du magst

Origin my.oschina.net/u/4789384/blog/5517169
Empfohlen
Rangfolge