Migrationsleitfaden zu Databricks Runtime 7.x (nicht unterstützt)

Dieser Leitfaden unterstützt Sie bei der Migration Ihrer Azure Databricks-Workloads von Databricks Runtime 6.x, das auf Apache Spark 2.4 basiert, zu Databricks Runtime 7.3 LTS (nicht unterstützt), das auf Spark 3.0 basiert.

In diesem Leitfaden werden die Änderungen hinsichtlich des Spark 3.0-Verhaltens aufgeführt, die eine Aktualisierung von Azure Databricks-Workloads erforderlich machen können. Zu diesen Änderungen gehören unter anderem die vollständige Abschaffung der Unterstützung für Python 2, das Upgrade auf Scala 2.12, die vollständige Unterstützung für JDK 11 und die Umstellung vom gregorianischen auf den proleptischen Kalender für Datumswerte und Zeitstempel.

Dieser Leitfaden ist eine Ergänzung zum Migrationsleitfaden zu Databricks Runtime 7.3 LTS (nicht unterstützt).

Informationen zum Migrieren zwischen Databricks Runtime-Versionen finden Sie im Databricks Runtime-Migrationshandbuch.

Neue Features und Verbesserungen in Databricks Runtime 7.x

Eine Liste der neuen Features, Verbesserungen und Bibliotheksupgrades, die in Databricks Runtime 7.3 LTS enthalten sind, finden Sie in den Versionshinweisen der jeweiligen Databricks Runtime-Version, von der aus Sie migrieren. Zu den unterstützten Databricks Runtime 7.x-Versionen gehören folgende:

Nach dem Release bereitgestellte Wartungsupdates sind unter Wartungsupdates für Databricks Runtime (archiviert) aufgeführt.

Systemumgebung für Databricks Runtime 7.3 LTS

  • Betriebssystem: Ubuntu 18.04.5 LTS
  • Java:
    • 7.3 LTS: Zulu 8.48.0.53-CA-linux64 (Build 1.8.0_265-b11)
  • Scala: 2.12.10
  • Python: 3.7.5
  • R: 3.6.3 (2020-02-29)
  • Delta Lake 0.7.0

Wichtige Verhaltensänderungen in Apache Spark 3.0

Die folgenden Verhaltensänderungen zwischen Spark 2.4 und Spark 3.0 machen möglicherweise eine Aktualisierung von Azure Databricks-Workloads erforderlich, wenn Sie von Databricks Runtime 6.x zu Databricks Runtime 7.x migrieren.

Hinweis

Dieser Artikel enthält eine Liste der wichtigen Änderungen am Spark-Verhalten, die Sie bei der Migration zu Databricks Runtime 7.x berücksichtigen sollten. Eine vollständige Liste der Verhaltensänderungen finden Sie im Spark 3.0.1-Migrationsleitfaden.

Core

  • In Spark 3.0 wird der veraltete Akkumulator v1 entfernt.
  • Die Ereignisprotokolldatei wird als UTF-8-Codierung geschrieben, und der Spark-Verlaufsserver gibt Ereignisprotokolldateien als UTF-8-Codierung wieder. Zuvor verwendete Spark zum Schreiben der Ereignisprotokolldatei den Standardzeichensatz des Treiber-JVM-Prozesses. Aus diesem Grund wird der Spark-Verlaufsserver von Spark 2.x benötigt, um im Falle einer inkompatiblen Codierung die alten Ereignisprotokolldateien zu lesen.
  • Es wird ein neues Protokoll zum Abrufen von Shuffleblöcken verwendet. Es wird empfohlen, externe Shuffledienste zu aktualisieren, wenn Spark 3.0-Anwendungen ausgeführt werden. Sie können weiterhin die alten externen Shuffledienste verwenden, indem Sie die Konfiguration spark.shuffle.useOldFetchProtocol auf true festlegen. Andernfalls kann es bei Spark zu Fehlermeldungen wie IllegalArgumentException: Unexpected message type: <number> kommen.

PySpark

  • In Spark 3.0 wurde Column.getItem korrigiert, sodass Column.apply nicht aufgerufen wird. Wenn also Column als Argument für getItem verwendet wird, sollte der Indizierungsoperator verwendet werden. Zum Beispiel sollte map_col.getItem(col('id')) durch map_col[col('id')] ersetzt werden.
  • Ab Spark 3.0 werden Row-Feldnamen bei der Konstruktion mit benannten Argumenten für Python-Version 3.6 und höher nicht mehr alphabetisch sortiert, und die Reihenfolge der Felder entspricht der eingegebenen Reihenfolge. Um (wie in Spark 2.4) standardmäßig sortierte Felder zu aktivieren, legen Sie die Umgebungsvariable PYSPARK_ROW_FIELD_SORTING_ENABLED sowohl für Executors als auch für Treiber auf true fest. Diese Umgebungsvariable muss für alle Executors und Treiber gleich sein. Andernfalls kann es zu Fehlern oder falschen Antworten kommen. Bei Python-Versionen vor Version 3.6 sind die Feldnamen ausschließlich alphabetisch sortiert.
  • Die Unterstützung für Python 2 wurde eingestellt (SPARK-27884).

Strukturiertes Streaming

  • In Spark 3.0 erzwingt das strukturierte Streaming die Umwandlung in ein Quellschema, das NULL-Werte zulässt, wenn dateibasierte Datenquellen wie Text, JSON, CSV, Parquet und ORC über spark.readStream(...) verwendet werden. Bisher wurde die NULL-Zulässigkeit im Quellschema berücksichtigt. Dies führte jedoch zu Problemen beim Debuggen mit NPE. Um das vorherige Verhalten wiederherzustellen, legen Sie spark.sql.streaming.fileSource.schema.forceNullable auf false fest.
  • Spark 3.0 behebt das Konsistenzproblem beim äußeren Stream-Stream-Join, der das Zustandsschema ändert. Weitere Informationen finden Sie unter SPARK-26154. Wenn Sie Ihre Abfrage von einem Prüfpunkt aus starten, der mit Spark 2.x erstellt wurde und einen äußeren Stream-Stream-Join verwendet, kommt es in Spark 3.0 zu einem Abfragefehler. Um die Ausgaben neu zu berechnen, verwerfen Sie den Prüfpunkt, und geben Sie die vorherigen Eingaben erneut wieder.
  • In Spark 3.0 wurde die veraltete Klasse org.apache.spark.sql.streaming.ProcessingTime entfernt. Verwenden Sie stattdessen org.apache.spark.sql.streaming.Trigger.ProcessingTime. Ebenso wurde org.apache.spark.sql.execution.streaming.continuous.ContinuousTrigger zugunsten von Trigger.Continuous entfernt und org.apache.spark.sql.execution.streaming.OneTimeTrigger wurde zugunsten von Trigger.Once ausgeblendet. Siehe SPARK-28199.

SQL, Datasets und DataFrame

  • In Spark 3.0 wird beim Einfügen eines Werts in eine Tabellenspalte mit einem anderen Datentyp eine Typumwandlung gemäß ANSI SQL-Standard durchgeführt. Bestimmte unangemessene Typumwandlungen, beispielsweise die Konvertierung von string in int und double in boolean, sind unzulässig. Es wird eine Laufzeitausnahme ausgelöst, wenn der Wert für den Datentyp der Spalte außerhalb des zulässigen Bereichs liegt. In Spark-Version 2.4 und Vorgängerversionen sind Typkonvertierungen während einer Tabelleneinfügung erlaubt, solange es sich um einen gültigen Cast handelt. Wenn ein Wert, der außerhalb des zulässigen Bereichs liegt, in ein integrales Feld eingefügt wird, werden die niederwertigen Bits des Werts eingefügt (wie bei einer numerischen Java/Scala-Typumwandlung). Wenn beispielsweise der Wert 257 in ein Feld vom Typ „Byte“ eingefügt wird, lautet das Ergebnis 1. Das Verhalten wird durch die Option spark.sql.storeAssignmentPolicy gesteuert, wobei der Standardwert „ANSI“ lautet. Durch Festlegen der Option auf „Legacy“ wird das vorherige Verhalten wiederhergestellt.
  • In Spark 3.0 werden bei der Umwandlung von Zeichenfolgenwerten in integrale Typen („tinyint“, „smallint“, „int“ und „bigint“), datetime-Typen (Datum, Zeitstempel und Intervall) und boolesche Typen die führenden und nachgestellten Leerzeichen (<= ACSII 32) vor der Umwandlung in diese Typenwerte abgeschnitten. Beispielsweise gibt cast(' 1\t' as int) den Wert 1, cast(' 1\t' as boolean) den Wert true und cast('2019-10-10\t as date) den Datumswert 2019-10-10 zurück. In Spark werden bis zur Version 2.4 bei der Umwandlung von Zeichenfolgen in integrale und boolesche Werte die Leerzeichen auf beiden Seiten nicht abgeschnitten, sodass die obigen Ergebnisse null lauten, während bei datetime-Werten nur die Leerzeichen am Ende (= ASCII 32) entfernt werden. Siehe https://databricks.com/blog/2020/07/22/a-comprehensive-look-at-dates-and-timestamps-in-apache-spark-3-0.html.
  • In Spark 3.0 wurden die veralteten Methoden SQLContext.createExternalTable und SparkSession.createExternalTable zugunsten ihrer Ersetzung createTable entfernt.
  • In Spark 3.0 wird die Konfiguration spark.sql.crossJoin.enabled zur internen Konfiguration und ist standardmäßig auf TRUE festgelegt, sodass Spark standardmäßig keine Ausnahme für SQL mit impliziten Kreuzverknüpfungen auslöst.
  • In Spark 3.0 wurde die Argumentreihenfolge der trim-Funktion von TRIM(trimStr, str) in TRIM(str, trimStr) geändert, um mit anderen Datenbanken kompatibel zu sein.
  • In Spark wurden bis zur Version 2.4 unabsichtlich SQL-Abfragen wie FROM <table> oder FROM <table> UNION ALL FROM <table> unterstützt. Im Hive-Stil FROM <table> SELECT <expr> darf die SELECT-Klausel nicht fehlen. Weder Hive noch Presto unterstützen diese Syntax. Daher werden diese Abfragen ab Spark 3.0 als ungültig betrachtet.
  • Ab Spark 3.0 wird die Dataset- und DataFrame-API unionAll nicht mehr als veraltet eingestuft. Sie ist ein Alias für union.
  • Bis zur Spark-Version 2.4 behandelt der Parser der JSON-Datenquelle leere Zeichenfolgen für einige Datentypen wie IntegerType als NULL. Für FloatType und DoubleType kommt es bei leeren Zeichenfolgen zu einem Fehler, und es werden Ausnahmen ausgelöst. Seit Spark 3.0 sind leere Zeichenfolgen nicht mehr zulässig, und es werden Ausnahmen für alle Datentypen außer StringType und BinaryType ausgelöst.
  • Seit Spark 3.0 unterstützen die from_json-Funktionen zwei Modi: PERMISSIVE und FAILFAST. Die Modi können über die Option mode festgelegt werden. Der Standardmodus lautet jetzt PERMISSIVE. In früheren Versionen entsprach das Verhalten von from_json weder PERMISSIVE noch FAILFAST,, insbesondere bei der Verarbeitung von nicht wohlgeformten JSON-Datensätzen. Beispielsweise wurde die JSON-Zeichenfolge {"a" 1} mit dem Schema a INT von früheren Versionen in null konvertiert, während Spark 3.0 eine Konvertierung in Row(null) durchführt.

DDL-Anweisungen

  • In Spark 3.0 verwendet CREATE TABLE ohne einen bestimmten Anbieter den Wert von spark.sql.sources.default als Anbieter. In Spark Version 2.4 und niedrigeren Versionen war dies Hive. Um das Verhalten vor Spark 3.0 wiederherzustellen, können Sie spark.sql.legacy.createHiveTableByDefault.enabled auf true festlegen.
  • In Spark 3.0 wird beim Einfügen eines Werts in eine Tabellenspalte mit einem anderen Datentyp eine Typumwandlung gemäß ANSI SQL-Standard durchgeführt. Bestimmte unangemessene Typumwandlungen, beispielsweise die Konvertierung von string in int und double in boolean, sind unzulässig. Es wird eine Laufzeitausnahme ausgelöst, wenn der Wert für den Datentyp der Spalte außerhalb des zulässigen Bereichs liegt. In Spark-Version 2.4 und Vorgängerversionen sind Typkonvertierungen während einer Tabelleneinfügung erlaubt, solange es sich um einen gültigen Cast handelt. Wenn ein Wert, der außerhalb des zulässigen Bereichs liegt, in ein integrales Feld eingefügt wird, werden die niederwertigen Bits des Werts eingefügt (wie bei einer numerischen Java/Scala-Typumwandlung). Wenn beispielsweise der Wert 257 in ein Feld vom Typ „Byte“ eingefügt wird, lautet das Ergebnis 1. Das Verhalten wird durch die Option spark.sql.storeAssignmentPolicy gesteuert, wobei der Standardwert „ANSI“ lautet. Durch Festlegen der Option auf „Legacy“ wird das vorherige Verhalten wiederhergestellt.
  • In Spark 3.0 gibt SHOW CREATE TABLE immer Spark-DDL zurück, auch wenn es sich bei der angegebenen Tabelle um eine Hive-SerDe-Tabelle handelt. Verwenden Sie zum Generieren von Hive-DDL stattdessen den Befehl SHOW CREATE TABLE AS SERDE.
  • In Spark 3.0 ist eine Spalte des Typs CHAR in Nicht-Hive-SerDe-Tabellen unzulässig, und CREATE/ALTER TABLE-Befehle führen zu einem Fehler, wenn der CHAR-Typ erkannt wird. Verwenden Sie stattdessen den Typ STRING. In Spark 2.4 und niedrigeren Versionen wird der Typ CHAR als Typ STRING behandelt, und der length-Parameter wird einfach ignoriert.

Benutzerdefinierte und integrierte Funktionen

  • In Spark 3.0 ist die Verwendung von org.apache.spark.sql.functions.udf(AnyRef, DataType) standardmäßig nicht erlaubt. Legen Sie spark.sql.legacy.allowUntypedScalaUDF auf true fest, um sie weiterhin zu verwenden. Wenn org.apache.spark.sql.functions.udf(AnyRef, DataType) in Spark 2.4 und niedriger einen Scala-Funktionsabschluss mit einem Argument eines primitiven Typs abruft, gibt die zurückgegebene benutzerdefinierte Funktion NULL zurück, wenn der Eingabewert NULL lautet. In Spark 3.0 gibt die benutzerdefinierte Funktion dagegen den Standardwert des Java-Typs zurück, wenn der Eingabewert NULL ist. Beispielsweise gibt val f = udf((x: Int) => x, IntegerType), f($"x") in Spark 2.4 und niedriger NULL zurück, wenn die Spalte x NULL ist, während in Spark 3.0 der Wert 0 zurückgegeben wird. Diese Verhaltensänderung wird eingeführt, da Spark 3.0 standardmäßig mit Scala 2.12 erstellt wird.
  • In Spark 2.4 und niedrigeren Versionen können Sie eine Zuordnung mit doppelten Schlüsseln über integrierte Funktionen wie CreateMap, StringToMap usw. erstellen. Das Verhalten von „map“ mit doppelten Schlüsseln ist undefiniert, z. B. werden bei einer map-Suche die doppelten Schlüssel zuerst angezeigt, bei Dataset.collect werden die doppelten Schlüssel zuletzt angezeigt, MapKeys gibt doppelte Schlüssel zurück usw. In Spark 3.0 wird eine RuntimeException ausgelöst, wenn doppelte Schlüssel gefunden werden. Sie können spark.sql.mapKeyDedupPolicy auf LAST_WIN festlegen, um map-Schlüssel mit der „last wins“-Richtlinie zu deduplizieren. Benutzer können weiterhin map-Werte mit doppelten Schlüsseln aus Datenquellen lesen, die dies nicht erzwingen (z. B. Parquet), das Verhalten ist undefiniert.

Datenquellen

  • In Spark 2.4 und niedrigeren Versionen wird der Wert einer Partitionsspalte in NULL konvertiert, wenn er nicht in ein entsprechendes vom Benutzer bereitgestelltes Schema umgewandelt werden kann. In Spark 3.0 wird der Wert der Partitionsspalte mit einem vom Benutzer angegebenen Schema validiert. Wenn die Validierung fehlschlägt, wird eine Ausnahme ausgelöst. Sie können diese Validierung deaktivieren, indem Sie spark.sql.sources.validatePartitionColumns auf false festlegen.
  • Bis zur Spark-Version 2.4 behandelt der Parser der JSON-Datenquelle leere Zeichenfolgen für einige Datentypen wie IntegerType als NULL. Für FloatType, DoubleType, DateType und TimestampType kommt es bei leeren Zeichenfolgen zu einem Fehler, und es werden Ausnahmen ausgelöst. In Spark 3.0 sind leere Zeichenfolgen nicht zulässig, und es werden Ausnahmen für alle Datentypen außer StringType und BinaryType ausgelöst. Das frühere Verhalten, eine leere Zeichenfolge zuzulassen, kann wiederhergestellt werden, indem spark.sql.legacy.json.allowEmptyString.enabled auf true festgelegt wird.
  • Wenn in Spark 3.0 Dateien oder Unterverzeichnisse während der rekursiven Verzeichnisauflistung verschwinden (d. h. sie erscheinen in einer Zwischenauflistung, können jedoch in späteren Phasen der rekursiven Verzeichnisauflistung nicht mehr gelesen oder aufgelistet werden, entweder aufgrund gleichzeitiger Dateilöschungen oder aufgrund von Konsistenzproblemen im Objektspeicher), schlägt die Auflistung mit einer Ausnahme fehl – es sei denn, spark.sql.files.ignoreMissingFiles lautet true (Standardwert = FALSE). In früheren Versionen wurden diese fehlenden Dateien oder Unterverzeichnisse ignoriert. Beachten Sie, dass diese Verhaltensänderung nur während der anfänglichen Auflistung der Tabellendateien (oder während REFRESH TABLE) gilt, nicht während der Abfrageausführung: Die wesentliche Änderung ist, dass spark.sql.files.ignoreMissingFiles nun während der Auflistung der Tabellendateien und der Abfrageplanung berücksichtigt wird, nicht nur bei der Abfrageausführung.
  • In Spark 2.4 und Vorgängerversionen konvertiert die CSV-Datenquelle eine falsch formatierte CSV-Zeichenfolge in eine Zeile mit allen NULL-Werten im PERMISSIVE-Modus. In Spark 3.0 kann die zurückgegebene Zeile Nicht-NULL-Felder enthalten, wenn einige der CSV-Spaltenwerte erfolgreich analysiert und in die gewünschten Typen konvertiert wurden.
  • In Spark 3.0 wird der logische Parquet-Typ TIMESTAMP_MICROS standardmäßig zum Speichern von TIMESTAMP-Spalten verwendet. In Spark 2.4 und niedriger werden TIMESTAMP-Spalten als INT96 in Parquet-Dateien gespeichert. Beachten Sie, dass einige SQL-Systeme wie Hive 1.x und Impala 2.x nur INT96-Zeitstempel lesen können. Sie können spark.sql.parquet.outputTimestampType auf INT96 festlegen, um das vorherige Verhalten wiederherzustellen und die Interoperabilität zu erhalten.
  • Wenn in Spark 3.0 Avro-Dateien mit einem vom Benutzer bereitgestellten Schema geschrieben werden, werden die Felder anstelle von Positionen anhand von Feldnamen zwischen dem catalyst- und dem Avro-Schema abgeglichen.

Abfrage-Engine

  • In Spark 3.0 schlägt eine Datasetabfrage fehl, wenn sie einen mehrdeutigen Spaltenverweis enthält, der durch eine Selbstverknüpfung verursacht wird. Ein typisches Beispiel: val df1 = ...; val df2 = df1.filter(...);, then df1.join(df2, df1("a") > df2("a")) liefert ein leeres Ergebnis, was ziemlich verwirrend ist. Das liegt daran, dass Spark keine Datasetspaltenverweise auflösen kann, die auf selbstverknüpfte Tabellen zeigen, und df1("a") ist in Spark exakt dasselbe wie df2("a"). Um das Verhalten vor Spark 3.0 wiederherzustellen, können Sie spark.sql.analyzer.failAmbiguousSelfJoin auf false festlegen.
  • In Spark 3.0 werden Zahlen in wissenschaftlicher Notation (z. B. 1E2) als Double analysiert. In Spark 2.4 und niedrigeren Versionen werden sie als Decimal analysiert. Um das Verhalten vor Spark 3.0 wiederherzustellen, können Sie spark.sql.legacy.exponentLiteralAsDecimal.enabled auf true festlegen.
  • In Spark 3.0 wird die Konfiguration spark.sql.crossJoin.enabled zu einer internen Konfiguration und ist standardmäßig auf TRUE festgelegt. Spark löst in der Standardeinstellung keine Ausnahmen für SQL mit impliziten Kreuzverknüpfungen aus.
  • In Spark 2.4 und niedrigeren Versionen entspricht „float/double -0.0“ semantisch 0.0, aber -0.0 und 0.0 werden als unterschiedliche Werte betrachtet, wenn sie in Aggregatgruppierungsschlüsseln, Fensterpartitionsschlüsseln und Joinschlüsseln verwendet werden. In Spark 3.0 wurde dieser Fehler behoben. Zum Beispiel gibt Seq(-0.0, 0.0).toDF("d").groupBy("d").count() in Spark 3.0 [(0.0, 2)] und in Spark 2.4 und niedrigeren Versionen [(0.0, 1), (-0.0, 1)] zurück.
  • In Spark 3.0 werden TIMESTAMP-Literale unter Verwendung der SQL-Konfiguration spark.sql.session.timeZone in Zeichenfolgen umgewandelt. In Spark 2.4 und Vorgängerversionen wird bei der Konvertierung die Standardzeitzone der Java-VM verwendet.
  • In Spark 3.0 wird in binären Vergleichen mit Datumswerten/Zeitstempeln String in Date/Timestamp umgewandelt. Das vorherige Verhalten der Umwandlung von Date/Timestamp in String kann wiederhergestellt werden, indem Sie spark.sql.legacy.typeCoercion.datetimeToString.enabled auf true festlegen.
  • In Spark 2.4 und niedriger werden ungültige Zeitzonen-IDs automatisch ignoriert und durch GMT-Zeitzone ersetzt, z. B. in der from_utc_timestamp-Funktion. In Spark 3.0 werden solche Zeitzonen-IDs abgelehnt, und Spark löst eine java.time.DateTimeException aus.
  • In Spark 3.0 wird der proleptische gregorianische Kalender beim Analysieren, Formatieren und Konvertieren von Daten und Zeitstempeln sowie beim Extrahieren von Unterkomponenten wie Jahren, Tagen usw. verwendet. Spark 3.0 verwendet Java 8-API-Klassen aus den java.time-Paketen, die auf ISO-Chronologie basieren. In Spark 2.4 und Vorgängerversionen werden diese Vorgänge mithilfe des Hybridkalenders (Julianisch + Gregorianisch) ausgeführt. Die Änderungen wirken sich auf die Ergebnisse für Datumsangaben vor dem 15. Oktober 1582 (gregorianisch) aus und betreffen die folgende Spark 3.0-API:
    • Analyse/Formatierung von Zeitstempeln/Datumszeichenfolgen. Dies wirkt sich auf CSV/JSON-Datenquellen und auf die Funktionen unix_timestamp, date_format, to_unix_timestamp, from_unixtime, to_date, to_timestamp aus, wenn vom Benutzer angegebene Muster für Analyse und Formatierung verwendet werden. In Spark 3.0 werden eigene Musterzeichenfolgen in sql-ref-datetime-pattern.md definiert, die im Hintergrund über java.time.format.DateTimeFormatter implementiert werden. Die neue Implementierung führt eine strenge Überprüfung der zugehörigen Eingabe durch. Zum Beispiel kann der Zeitstempel 2015-07-22 10:00:00 nicht analysiert werden, wenn das Muster yyyy-MM-dd lautet, da der Parser nicht die gesamte Eingabe verarbeitet. Ein weiteres Beispiel: Die 31/01/2015 00:00-Eingabe kann nicht anhand des Musters dd/MM/yyyy hh:mm analysiert werden, weil hh Stunden im Bereich 1–12 voraussetzt. In Spark 2.4 und Vorgängerversionen wird java.text.SimpleDateFormat für die Konvertierung von Zeitstempeln/Datumszeichenfolgen verwendet, und die unterstützten Muster sind in simpleDateFormat beschrieben. Das vorherige Verhalten kann wiederhergestellt werden, indem Sie spark.sql.legacy.timeParserPolicy auf LEGACY festlegen.
    • Die Funktionen weekofyear, weekday, dayofweek, date_trunc, from_utc_timestamp, to_utc_timestamp und unix_timestamp verwenden die java.time-API zur Berechnung der Wochennummer des Jahres, der Wochentagsnummer sowie zur Konvertierung aus bzw. in TimestampType-Werte in der UTC-Zeitzone.
    • Die JDBC-Optionen lowerBound und upperBound werden auf die gleiche Weise in TimestampType/DateType-Werte umgewandelt wie bei der Umwandlung von Zeichenfolgen in TimestampType/DateType-Werte. Die Konvertierung basiert auf dem proleptischen gregorianischen Kalender und der Zeitzone, die in der SQL-Konfiguration spark.sql.session.timeZone definiert ist. In Spark 2.4 und Vorgängerversionen basiert die Konvertierung auf dem Hybridkalender (Julianisch + Gregorianisch) und auf der Standardzeitzone des Systems.
    • Formatierung von TIMESTAMP und DATE-Literalen.
    • Erstellen von typisierten TIMESTAMP- und DATE-Literalen aus Zeichenfolgen. In Spark 3.0 erfolgt die Zeichenfolgenkonvertierung in typisierte TIMESTAMP/DATE-Literale durch eine Umwandlung in TIMESTAMP/DATE-Werte. Zum Beispiel entspricht TIMESTAMP '2019-12-23 12:59:30' semantisch CAST('2019-12-23 12:59:30' AS TIMESTAMP). Falls die Eingabezeichenfolge keine Informationen über die Zeitzone enthält, wird die Zeitzone aus der SQL-Konfiguration spark.sql.session.timeZone verwendet. In Spark 2.4 und niedrigeren Versionen basiert die Konvertierung auf der JVM-Systemzeitzone. Die verschiedenen Quellen der Standardzeitzone können das Verhalten von typisierten TIMESTAMP- und DATE-Literalen ändern.

Apache Hive

  • In Spark 3.0 wurde die integrierte Hive-Version von 1.2 auf 2.3 aktualisiert, was sich wie folgt auswirkt:
    • Möglicherweise müssen Sie spark.sql.hive.metastore.version und spark.sql.hive.metastore.jars gemäß der Version des Hive-Metastores festlegen, mit dem Sie eine Verbindung herstellen möchten. Beispiel: Legen Sie spark.sql.hive.metastore.version auf 1.2.1 und spark.sql.hive.metastore.jars auf maven fest, wenn Ihre Hive-Metastore-Version 1.2.1 ist.
    • Sie müssen Ihre benutzerdefinierten SerDe-Implementierungen zu Hive 2.3 migrieren oder einen eigenen Spark mit Profil hive-1.2 erstellen. Weitere Informationen finden Sie unter HIVE-15167.
    • Die dezimale Zeichenfolgendarstellung kann zwischen Hive 1.2 und Hive 2.3 unterschiedlich sein, wenn der TRANSFORM-Operator in SQL für die Skripttransformation verwendet wird, was vom Verhalten von Hive abhängt. In Hive 1.2 werden bei der Zeichenfolgendarstellung die Nullen am Ende weggelassen. In Hive 2.3 dagegen wird immer auf 18 Stellen aufgefüllt, gegebenenfalls mit nachgestellten Nullen.
    • In Databricks Runtime 7.x untersagt Spark beim Lesen einer Hive-SerDe-Tabelle standardmäßig das Lesen von Dateien unterhalb eines Unterverzeichnisses, das keine Tabellenpartition ist. Legen Sie zur Aktivierung die Konfiguration spark.databricks.io.hive.scanNonpartitionedDirectory.enabled auf true fest. Dies wirkt sich nicht auf native Spark-Tabellenleser und -Dateileser aus.

MLlib

  • Das in Version 2.3 als veraltet eingestufte OneHotEncoder wird in Version 3.0 entfernt, und OneHotEncoderEstimator wird in OneHotEncoder umbenannt.
  • Das in Version 2.3 als veraltet eingestufte org.apache.spark.ml.image.ImageSchema.readImages wird in Version 3.0 entfernt. Verwenden Sie stattdessen spark.read.format('image').
  • org.apache.spark.mllib.clustering.KMeans.train mit „param Int runs“, das in Version 2.1 als veraltet eingestuft wurde, wird in Version 3.0 entfernt. Verwenden Sie stattdessen die train-Methode ohne „runs“.
  • Das in Version 2.0 als veraltet eingestufte org.apache.spark.mllib.classification.LogisticRegressionWithSGD wird in Version 3.0 entfernt. Verwenden Sie stattdessen org.apache.spark.ml.classification.LogisticRegression oder spark.mllib.classification.LogisticRegressionWithLBFGS.
  • Das in Version 2.1 als veraltet eingestufte und in Version 3.0 entfernte org.apache.spark.mllib.feature.ChiSqSelectorModel.isSorted ist nicht für die Verwendung durch Unterklassen gedacht.
  • Das in Version 2.0 als veraltet eingestufte org.apache.spark.mllib.regression.RidgeRegressionWithSGD wird in Version 3.0 entfernt. Verwenden Sie org.apache.spark.ml.regression.LinearRegression mit elasticNetParam = 0.0. Hinweis: Der regParam-Standardwert für RidgeRegressionWithSGD lautet 0.01, aber 0.0 für LinearRegression.
  • Das in Version 2.0 als veraltet eingestufte org.apache.spark.mllib.regression.LassoWithSGD wird in Version 3.0 entfernt. Verwenden Sie org.apache.spark.ml.regression.LinearRegression mit elasticNetParam = 1.0. Hinweis: Der regParam-Standardwert für LassoWithSGD lautet 0.01, aber 0.0 für LinearRegression.
  • Das in Version 2.0 als veraltet eingestufte org.apache.spark.mllib.regression.LinearRegressionWithSGD wird in Version 3.0 entfernt. Verwenden Sie stattdessen org.apache.spark.ml.regression.LinearRegression oder LBFGS.
  • org.apache.spark.mllib.clustering.KMeans.getRuns und setRuns, die in Version 2.1 als veraltet eingestuft und in Version 3.0 entfernt wurden, haben seit Spark 2.0.0 keine Auswirkungen mehr.
  • Das in Version 2.4 als veraltet eingestufte und in Version 3.0 entfernte org.apache.spark.ml.LinearSVCModel.setWeightCol ist nicht für Benutzer gedacht.
  • In Version 3.0 wird org.apache.spark.ml.classification.MultilayerPerceptronClassificationModel auf MultilayerPerceptronParams erweitert, um die Trainingsparameter verfügbar zu machen. Als Ergebnis wurde layers in MultilayerPerceptronClassificationModel von Array[Int] in IntArrayParam geändert. Verwenden Sie MultilayerPerceptronClassificationModel.getLayers anstelle von MultilayerPerceptronClassificationModel.layers, um die layer-Größe abzurufen.
  • Das in Version 2.4.5 als veraltet eingestufte org.apache.spark.ml.classification.GBTClassifier.numTrees wird in Version 3.0 entfernt. Verwenden Sie stattdessen getNumTrees.
  • Das in Version 2.4 als veraltet eingestufte org.apache.spark.ml.clustering.KMeansModel.computeCost wird in Version 3.0 entfernt. Verwenden Sie stattdessen ClusteringEvaluator.
  • Die in Version 2.0 als veraltet eingestufte Membervariable „precision“ in org.apache.spark.mllib.evaluation.MulticlassMetrics wird in Version 3.0 entfernt. Verwenden Sie stattdessen „accuracy“.
  • Die in Version 2.0 als veraltet eingestufte Membervariable „recall“ in org.apache.spark.mllib.evaluation.MulticlassMetrics wird in Version 3.0 entfernt. Verwenden Sie stattdessen accuracy.
  • Die in Version 2.0 als veraltet eingestufte Membervariable fMeasure in org.apache.spark.mllib.evaluation.MulticlassMetrics wird in Version 3.0 entfernt. Verwenden Sie stattdessen accuracy.
  • Das in Version 2.0 als veraltet eingestufte org.apache.spark.ml.util.GeneralMLWriter.context wird in Version 3.0 entfernt. Verwenden Sie stattdessen session.
  • Das in Version 2.0 als veraltet eingestufte org.apache.spark.ml.util.MLWriter.context wird in Version 3.0 entfernt. Verwenden Sie stattdessen session.
  • Das in Version 2.0 als veraltet eingestufte org.apache.spark.ml.util.MLReader.context wird in Version 3.0 entfernt. Verwenden Sie stattdessen session.
  • abstract class UnaryTransformer[IN, OUT, T <: UnaryTransformer[IN, OUT, T]] wird in Version 3.0 in abstract class UnaryTransformer[IN: TypeTag, OUT: TypeTag, T <: UnaryTransformer[IN, OUT, T]] geändert.
  • In Spark 3.0 gibt eine logistische Regression mit mehreren Klassen in Pyspark jetzt (ordnungsgemäß) LogisticRegressionSummary und nicht die Unterklasse BinaryLogisticRegressionSummary zurück. Die zusätzlichen Methoden, die über BinaryLogisticRegressionSummary verfügbar gemacht werden, würden in diesem Fall ohnehin nicht funktionieren. (SPARK-31681)
  • In Spark 3.0 stellen pyspark.ml.param.shared.Has*-Mixins keine set*(self, value)-Setter-Methoden mehr zur Verfügung, sondern verwenden stattdessen den jeweiligen self.set(self.*, value). Weitere Informationen finden Sie unter SPARK-29093. (SPARK-29093)

Andere Verhaltensänderungen

  • Das Upgrade auf Scala 2.12 umfasst die folgenden Änderungen:

    • Die Serialisierung von Paketzellen wird anders verarbeitet. Das folgende Beispiel veranschaulicht die Verhaltensänderung und deren Handhabung.

      Die Ausführung von foo.bar.MyObjectInPackageCell.run(), wie in der folgenden Paketzelle definiert, löst den Fehler java.lang.NoClassDefFoundError: Could not initialize class foo.bar.MyObjectInPackageCell$ aus.

      package foo.bar
      
      case class MyIntStruct(int: Int)
      
      import org.apache.spark.sql.SparkSession
      import org.apache.spark.sql.functions._
      import org.apache.spark.sql.Column
      
      object MyObjectInPackageCell extends Serializable {
      
        // Because SparkSession cannot be created in Spark executors,
        // the following line triggers the error
        // Could not initialize class foo.bar.MyObjectInPackageCell$
        val spark = SparkSession.builder.getOrCreate()
      
        def foo: Int => Option[MyIntStruct] = (x: Int) => Some(MyIntStruct(100))
      
        val theUDF = udf(foo)
      
        val df = {
          val myUDFInstance = theUDF(col("id"))
          spark.range(0, 1, 1, 1).withColumn("u", myUDFInstance)
        }
      
        def run(): Unit = {
          df.collect().foreach(println)
        }
      }
      

      Um diesen Fehler zu umgehen, können Sie MyObjectInPackageCell in eine serialisierbare Klasse einschließen.

    • In bestimmten Fällen, in denen DataStreamWriter.foreachBatch verwendet wird, ist eine Aktualisierung des Quellcodes erforderlich. Diese Änderung ist auf die Tatsache zurückzuführen, dass Scala 2.12 eine automatische Konvertierung von Lambda-Ausdrücken in SAM-Typen durchführt, was zu Mehrdeutigkeiten führen kann.

      Beispielsweise kann der folgende Scala-Code nicht kompiliert werden:

      streams
        .writeStream
        .foreachBatch { (df, id) => myFunc(df, id) }
      

      Um den Kompilierungsfehler zu beheben, ändern Sie foreachBatch { (df, id) => myFunc(df, id) } in foreachBatch(myFunc _), oder verwenden Sie explizit die Java-API: foreachBatch(new VoidFunction2 ...).

  • Da die Apache Hive-Version, die für die Verarbeitung von benutzerdefinierten Hive-Funktionen und Hive-SerDe-Implementierungen verwendet wird, auf 2.3 aktualisiert wurde, sind zwei Änderungen erforderlich:

    • Die Hive-Schnittstelle SerDe wird durch eine abstrakte Klasse AbstractSerDe ersetzt. Für jede benutzerdefinierte Hive-SerDe-Implementierung ist eine Migration zu AbstractSerDe erforderlich.
    • Die Festlegung von spark.sql.hive.metastore.jars auf builtin bedeutet, dass der Hive 2.3-Metastore-Client für den Zugriff auf Metastores für Databricks Runtime 7.x verwendet wird. Wenn Sie auf Hive 1.2-basierte externe Metastores zugreifen müssen, legen Sie spark.sql.hive.metastore.jars auf den Ordner fest, der Hive 1.2-JARs enthält.

Veraltete und entfernte Funktionen

  • DATASKIPPING INDEX wurde in Databricks Runtime 4.3 als veraltet eingestuft und in Databricks Runtime 7.x entfernt. Es wird empfohlen, stattdessen Delta-Tabellen zu verwenden, die verbesserte Funktionen zum Überspringen von Daten bieten.
  • In Databricks Runtime 7.x verwendet die zugrunde liegende Version Apache Spark Scala 2.12. Da mit Scala 2.11 kompilierte Bibliotheken Databricks Runtime 7.x-Cluster auf unerwartete Weise deaktivieren können, installieren Cluster, auf denen Databricks Runtime 7.x ausgeführt wird, keine Bibliotheken, die zur Installation in allen Clustern konfiguriert sind. Die Registerkarte „Bibliotheken“ für eine Clusters zeigt den Status Skipped und eine Meldung an, in der die Änderungen bezüglich der Handhabung von Bibliotheken erläutert werden. Wenn Sie jedoch über einen Cluster verfügen, der mit einer Vorgängerversion von Databricks Runtime erstellt wurde, bevor Version 3.20 der Azure Databricks-Plattform für Ihren Arbeitsbereich veröffentlicht wurde, und Sie diesen Cluster jetzt bearbeiten, um Databricks Runtime 7.x zu verwenden, werden alle Bibliotheken, die für die Installation in allen Clustern konfiguriert wurden, auf diesem Cluster installiert. In diesem Fall können inkompatible JARs in den installierten Bibliotheken dazu führen, dass der Cluster deaktiviert wird. Die Problemumgehung besteht darin, entweder den Cluster zu klonen oder einen neuen Cluster zu erstellen.

Bekannte Probleme

  • Die Analyse des Tages des Jahres mit dem Buchstaben „D“ liefert ein falsches Ergebnis, wenn das Jahresfeld fehlt. Dies kann in SQL-Funktionen wie to_timestamp auftreten, die datetime-Zeichenfolgen mithilfe einer Musterzeichenfolge in datetime-Werte analysieren. (SPARK-31939)
  • Join-/Fenster-/Aggregatschlüssel innerhalb von Unterabfragen können zu falschen Ergebnissen führen, wenn die Schlüssel die Werte -0.0 und 0.0 aufweisen. (SPARK-31958)
  • Eine Fensterabfrage kann mit einem mehrdeutigen Selbstverknüpfungsfehler unerwartet fehlschlagen. (SPARK-31956)
  • Streamingabfragen mit dropDuplicates-Operator können möglicherweise nicht mit dem von Spark 2.x geschriebenen Prüfpunkt neu gestartet werden. (SPARK-31990)