Apache Spark-code voor U-SQL-ontwikkelaars begrijpen

Belangrijk

Azure Data Lake Analytics op 29 februari 2024 buiten gebruik gesteld. Meer informatie over deze aankondiging.

Voor gegevensanalyse kan uw organisatie gebruikmaken van Azure Synapse Analytics of Microsoft Fabric.

Deze sectie bevat richtlijnen op hoog niveau voor het transformeren van U-SQL-scripts naar Apache Spark.

Inzicht in de U-SQL- en Spark-taal en verwerkingsparadigma's

Voordat u begint met het migreren van U-SQL-scripts van Azure Data Lake Analytics naar Spark, is het handig om de algemene taal en verwerkingsfilosofieën van de twee systemen te begrijpen.

U-SQL is een SQL-achtige declaratieve querytaal die gebruikmaakt van een gegevensstroomparadigma en waarmee u eenvoudig gebruikerscode kunt insluiten en uitschalen die is geschreven in .NET (bijvoorbeeld C#), Python en R. De gebruikersextensies kunnen eenvoudige expressies of door de gebruiker gedefinieerde functies implementeren, maar kunnen de gebruiker ook de mogelijkheid bieden om zogenaamde door de gebruiker gedefinieerde operators te implementeren die aangepaste operators implementeren om transformaties, extracties en schrijfuitvoer op rijsetniveau uit te voeren.

Spark is een scale-out framework met verschillende taalbindingen in Scala, Java, Python, .NET, enzovoort. Hierbij schrijft u voornamelijk uw code in een van deze talen, maakt u gegevensabstracties genaamd RDD (Resilient Distributed Datasets), dataframes en gegevenssets en gebruikt u vervolgens een LINQ-achtige domeinspecifieke taal (DSL) om ze te transformeren. Het biedt ook SparkSQL als een declaratieve subtaal voor de abstracties van het gegevensframe en de gegevensset. De DSL biedt twee categorieën van bewerkingen, transformaties en acties. Als u transformaties toepast op de gegevensabstracties, wordt de transformatie niet uitgevoerd, maar wordt het uitvoeringsplan opgebouwd dat met een actie wordt verzonden voor evaluatie (bijvoorbeeld het schrijven van het resultaat in een tijdelijke tabel of bestand of het afdrukken van het resultaat).

Wanneer u dus een U-SQL-script vertaalt naar een Spark-programma, moet u beslissen welke taal u wilt gebruiken om ten minste de abstractie van het gegevensframe te genereren (dit is momenteel de meest gebruikte gegevensabstractie) en of u de declaratieve gegevensstroomtransformaties wilt schrijven met behulp van DSL of SparkSQL. In sommige complexere gevallen moet u mogelijk uw U-SQL-script splitsen in een reeks Spark- en andere stappen die zijn geïmplementeerd met Azure Batch of Azure Functions.

Bovendien biedt Azure Data Lake Analytics U-SQL in een serverloze taakserviceomgeving waar resources worden toegewezen voor elke taak, terwijl Azure Synapse Spark, Azure Databricks en Azure HDInsight Spark aanbieden in de vorm van een clusterservice of met zogenaamde Spark-poolsjablonen. Bij het transformeren van uw toepassing moet u rekening houden met de gevolgen van het nu maken, aanpassen, schalen en buiten gebruik stellen van de clusters of pools.

U-SQL-scripts transformeren

U-SQL-scripts volgen het volgende verwerkingspatroon:

  1. Gegevens worden gelezen uit ongestructureerde bestanden, met behulp van de EXTRACT -instructie, een locatie- of bestandssetspecificatie, en de ingebouwde of door de gebruiker gedefinieerde extractor en het gewenste schema, of uit U-SQL-tabellen (beheerde of externe tabellen). Deze wordt weergegeven als een rijenset.
  2. De rijensets worden getransformeerd in meerdere U-SQL-instructies die U-SQL-expressies toepassen op de rijensets en nieuwe rijensets produceren.
  3. Ten slotte worden de resulterende rijensets uitgevoerd in bestanden met behulp van de OUTPUT instructie die de locatie(s) en een ingebouwde of door de gebruiker gedefinieerde uitvoerter opgeeft, of in een U-SQL-tabel.

Het script wordt lazily geëvalueerd, wat betekent dat elke extractie- en transformatiestap wordt samengesteld in een expressiestructuur en globaal wordt geëvalueerd (de gegevensstroom).

Spark-programma's zijn vergelijkbaar in die zin dat u Spark-connectors gebruikt om de gegevens te lezen en de dataframes te maken, vervolgens de transformaties op de dataframes toepast met behulp van de LINQ-achtige DSL of SparkSQL en het resultaat vervolgens schrijft in bestanden, tijdelijke Spark-tabellen, bepaalde typen programmeertalen of de console.

.NET-code transformeren

De expressietaal van U-SQL is C# en biedt verschillende manieren om aangepaste .NET-code uit te schalen met door de gebruiker gedefinieerde functies, door de gebruiker gedefinieerde operators en door de gebruiker gedefinieerde aggregators.

Azure Synapse en Azure HDInsight Spark bieden nu beide systeemeigen ondersteuning voor het uitvoeren van .NET-code met .NET voor Apache Spark. Dit betekent dat u sommige of alle door de gebruiker gedefinieerde .NET-functies mogelijk opnieuw kunt gebruiken met Spark. U-SQL gebruikt echter de .NET Framework, terwijl .NET voor Apache Spark is gebaseerd op .NET Core 3.1 of hoger.

U-SQL door de gebruiker gedefinieerde operators (UDO's) gebruiken het U-SQL UDO-model om uitgeschaalde uitvoering van de code van de operator mogelijk te maken. UDF's moeten dus worden herschreven in door de gebruiker gedefinieerde functies om in het Spark-uitvoeringsmodel te passen.

.NET voor Apache Spark biedt momenteel geen ondersteuning voor door de gebruiker gedefinieerde aggregators. Daarom moeten door de gebruiker gedefinieerde U-SQL-aggregators worden vertaald in door de gebruiker gedefinieerde Spark-aggregators die zijn geschreven in Scala.

Als u niet wilt profiteren van de mogelijkheden van .NET voor Apache Spark, moet u uw expressies herschrijven naar een equivalente Spark-, Scala-, Java- of Python-expressie, functie, aggregator of connector.

Als u een grote hoeveelheid .NET-logica in uw U-SQL-scripts hebt, neemt u contact met ons op via uw Microsoft-accountvertegenwoordiger voor verdere hulp.

De volgende details zijn voor de verschillende gevallen van .NET- en C#-gebruik in U-SQL-scripts.

Scalaire inline U-SQL C#-expressies transformeren

De expressietaal van U-SQL is C#. Veel van de scalaire inline U-SQL-expressies worden systeemeigen geïmplementeerd voor betere prestaties, terwijl complexere expressies kunnen worden uitgevoerd door aan te roepen in het .NET Framework.

Spark heeft een eigen scalaire expressietaal (als onderdeel van de DSL of in SparkSQL) en maakt het mogelijk om door de gebruiker gedefinieerde functies aan te roepen die zijn geschreven voor de JVM-, .NET- of Python-runtime.

Als u scalaire expressies in U-SQL hebt, moet u eerst de meest geschikte, systeemeigen begrepen Scalaire Spark-expressie vinden om de beste prestaties te krijgen, en vervolgens de andere expressies toewijzen aan een door de gebruiker gedefinieerde functie van de Spark-runtimetaal van uw keuze.

Houd er rekening mee dat .NET en C# een ander type semantiek hebben dan de JVM- en Python-runtimes en spark's DSL. Zie hieronder voor meer informatie over de type systeemverschillen.

Door de gebruiker gedefinieerde scalaire .NET-functies en door de gebruiker gedefinieerde aggregators transformeren

U-SQL biedt manieren om willekeurige scalaire .NET-functies aan te roepen en door de gebruiker gedefinieerde aggregators aan te roepen die zijn geschreven in .NET.

Spark biedt ook ondersteuning voor door de gebruiker gedefinieerde functies en door de gebruiker gedefinieerde aggregators die zijn geschreven in de meeste hostingtalen die kunnen worden aangeroepen vanuit Spark DSL en SparkSQL.

Zoals hierboven vermeld, ondersteunt .NET voor Apache Spark door de gebruiker gedefinieerde functies die zijn geschreven in .NET, maar biedt het geen ondersteuning voor door de gebruiker gedefinieerde aggregators. Dus voor door de gebruiker gedefinieerde functies kan .NET voor Apache Spark worden gebruikt, terwijl door de gebruiker gedefinieerde aggregators moeten worden geschreven in Scala voor Spark.

Door de gebruiker gedefinieerde operators (UDF's) transformeren

U-SQL biedt verschillende categorieën van door de gebruiker gedefinieerde operators (UDF's), zoals extractors, outputters, reducers, processors, appliers en combiners die kunnen worden geschreven in .NET (en - tot op zekere hoogte - in Python en R).

Spark biedt niet hetzelfde uitbreidbaarheidsmodel voor operators, maar heeft voor sommige vergelijkbare mogelijkheden.

Het Spark-equivalent aan extractors en outputters zijn Spark-connectors. Voor veel U-SQL-extractoren vindt u mogelijk een gelijkwaardige connector in de Spark-community. Voor anderen moet u een aangepaste connector schrijven. Als de U-SQL-extractor complex is en gebruikmaakt van verschillende .NET-bibliotheken, is het wellicht beter om in Scala een connector te bouwen die gebruikmaakt van interoperabiliteit om de .NET-bibliotheek aan te roepen die de werkelijke verwerking van de gegevens uitvoert. In dat geval moet u de .NET Core-runtime implementeren in het Spark-cluster en ervoor zorgen dat de .NET-bibliotheken waarnaar wordt verwezen compatibel zijn met .NET Standard 2.0.

De andere typen U-SQL UDF's moeten worden herschreven met behulp van door de gebruiker gedefinieerde functies en aggregators en de semantisch geschikte Spark DLS- of SparkSQL-expressie. Een processor kan bijvoorbeeld worden toegewezen aan een SELECT van verschillende UDF-aanroepen, verpakt als een functie die een dataframe als argument gebruikt en een dataframe retourneert.

Optionele bibliotheken van U-SQL transformeren

U-SQL biedt een set optionele en demobibliotheken die python-, R-, JSON-, XML-, AVRO-ondersteuning en enkele mogelijkheden voor Azure AI-services bieden.

Spark biedt zijn eigen Python- en R-integratie, respectievelijk pySpark en SparkR, en biedt connectors voor het lezen en schrijven van JSON, XML en AVRO.

Als u een script wilt transformeren dat verwijst naar de Azure AI-servicesbibliotheken, raden we u aan contact met ons op te stellen via uw Microsoft-accountvertegenwoordiger.

Getypte waarden transformeren

Omdat het typesysteem van U-SQL is gebaseerd op het .NET-typesysteem en Spark een eigen typesysteem heeft dat wordt beïnvloed door de hosttaalbinding, moet u ervoor zorgen dat de typen waarop u werkt dicht bij elkaar liggen en voor bepaalde typen kunnen de typebereiken, precisie en/of schaal enigszins afwijken. Bovendien worden waarden in U-SQL en Spark verschillend behandeld null .

Gegevenstypen

De volgende tabel bevat de equivalente typen in Spark, Scala en PySpark voor de opgegeven U-SQL-typen.

U-SQL Spark Scala PySpark
byte
sbyte ByteType Byte ByteType
int IntegerType Int IntegerType
uint
long LongType Long LongType
ulong
float FloatType Float FloatType
double DoubleType Double DoubleType
decimal DecimalType java.math.BigDecimal DecimalType
short ShortType Short ShortType
ushort
char Char
string StringType String StringType
DateTime DateType, TimestampType java.sql.Date, java.sql.Timestamp DateType, TimestampType
bool BooleanType Boolean BooleanType
Guid
byte[] BinaryType Array[Byte] BinaryType
SQL.MAP<K,V> MapType(keyType, valueType, valueContainsNull) scala.collection.Map MapType(keyType, valueType, valueContainsNull=True)
SQL.ARRAY<T> ArrayType(elementType, containsNull) scala.collection.Seq ArrayType(elementType, containsNull=True)

Zie voor meer informatie:

Behandeling van NULL

In Spark staan typen standaard NULL-waarden toe. In U-SQL markeert u expliciet scalaire, niet-objecten als null-waarde. Hoewel u met Spark een kolom kunt definiëren als niet-nullable, wordt de beperking niet afgedwongen en kan dit leiden tot een verkeerd resultaat.

In Spark geeft NULL aan dat de waarde onbekend is. Een Spark NULL-waarde verschilt van elke waarde, inclusief zichzelf. Vergelijkingen tussen twee Spark NULL-waarden, of tussen een NULL-waarde en een andere waarde, retourneren onbekend omdat de waarde van elke NULL onbekend is.

Dit gedrag verschilt van U-SQL, dat de C#-semantiek volgt, waarbij null elke waarde verschilt, maar gelijk is aan zichzelf.

Een SparkSQL-instructie SELECT die gebruikmaakt WHERE column_name = NULL , retourneert dus nul rijen, zelfs als er NULL-waarden in column_namezijn, terwijl in U-SQL de rijen worden geretourneerd waarvoor column_name is ingesteld op null. Op dezelfde manier retourneert een Spark-instructie SELECT die gebruikmaakt WHERE column_name != NULL van nul rijen, zelfs als er niet-null-waarden in column_namestaan, terwijl in U-SQL de rijen met een niet-null-waarde worden geretourneerd. Als u dus de u-SQL-semantiek voor null-controle wilt gebruiken, moet u respectievelijk isnull en isnotnull (of hun DSL-equivalent) gebruiken.

U-SQL-catalogusobjecten transformeren

Een belangrijk verschil is dat U-SQL-scripts gebruik kunnen maken van de bijbehorende catalogusobjecten, waarvan vele geen direct Spark-equivalent hebben.

Spark biedt wel ondersteuning voor de Hive Meta Store-concepten, voornamelijk databases, tabellen en weergaven, zodat u U-SQL-databases en -schema's kunt toewijzen aan Hive-databases en U-SQL-tabellen aan Spark-tabellen (zie Gegevens verplaatsen die zijn opgeslagen in U-SQL-tabellen), maar het biedt geen ondersteuning voor tabelwaardefuncties (TVF's), opgeslagen procedures, U-SQL-assembly's, externe gegevensbronnen, enzovoort.

U-SQL-codeobjecten, zoals weergaven, TVF's, opgeslagen procedures en assembly's, kunnen worden gemodelleerd via codefuncties en -bibliotheken in Spark en waarnaar wordt verwezen met behulp van de functie van de hosttaal en procedurele abstractiemechanismen (bijvoorbeeld door Python-modules te importeren of naar Scala-functies te verwijzen).

Als de U-SQL-catalogus is gebruikt voor het delen van gegevens en codeobjecten tussen projecten en teams, moeten gelijkwaardige mechanismen voor delen worden gebruikt (bijvoorbeeld Maven voor het delen van codeobjecten).

U-SQL-rijensetexpressies en scalaire expressies op basis van SQL transformeren

De kerntaal van U-SQL transformeert rijensets en is gebaseerd op SQL. Hier volgt een niet-uitputtende lijst met de meest voorkomende rijensetexpressies die worden aangeboden in U-SQL:

  • SELECT/FROM/WHERE/GROUP BY+Aggregaties+HAVING/ORDER BY+FETCH

  • INNER/OUTER/CROSS/SEMIJOIN Expressies

  • CROSS/OUTERAPPLY Expressies

  • PIVOT/UNPIVOT Expressies

  • VALUES rijsetconstructor

  • Expressies instellen UNION/OUTER UNION/INTERSECT/EXCEPT

Daarnaast biedt U-SQL verschillende scalaire expressies op basis van SQL, zoals

  • OVER vensterexpressies
  • verschillende ingebouwde aggregators en classificatiefuncties (SUMenz FIRST .)
  • Enkele van de meest bekende scalaire SQL-expressies: , , (NOT) IN, AND, enzovoortOR. LIKECASE

Spark biedt gelijkwaardige expressies in zowel de DSL- als SparkSQL-vorm voor de meeste van deze expressies. Sommige expressies die niet systeemeigen worden ondersteund in Spark, moeten worden herschreven met behulp van een combinatie van de systeemeigen Spark-expressies en semantisch equivalente patronen. Zal bijvoorbeeld OUTER UNION moeten worden omgezet in de equivalente combinatie van projecties en vakbonden.

Vanwege de verschillende verwerking van NULL-waarden komt een U-SQL-join altijd overeen met een rij als beide kolommen die worden vergeleken een NULL-waarde bevatten, terwijl een join in Spark niet overeenkomt met dergelijke kolommen, tenzij expliciete null-controles worden toegevoegd.

Andere U-SQL-concepten transformeren

U-SQL biedt ook verschillende andere functies en concepten, zoals federatieve query's op SQL Server databases, parameters, scalaire en lambda-expressievariabelen, systeemvariabelen en OPTION hints.

Federatieve query's op SQL Server databases/externe tabellen

U-SQL biedt gegevensbron en externe tabellen, evenals directe query's op Azure SQL Database. Hoewel Spark niet dezelfde objectabstracties biedt, biedt het Spark-connector voor Azure SQL Database die kan worden gebruikt om query's uit te voeren op SQL-databases.

U-SQL-parameters en -variabelen

Parameters en gebruikersvariabelen hebben gelijkwaardige concepten in Spark en hun hostingtalen.

In Scala kunt u bijvoorbeeld een variabele definiëren met het var trefwoord:

var x = 2 * 3;
println(x)

De systeemvariabelen van U-SQL (variabelen die beginnen met @@) kunnen worden onderverdeeld in twee categorieën:

  • Instelbare systeemvariabelen die kunnen worden ingesteld op specifieke waarden om het gedrag van scripts te beïnvloeden
  • Informatieve systeemvariabelen die informatie op systeem- en taakniveau opvragen

De meeste instelbare systeemvariabelen hebben geen direct equivalent in Spark. Sommige van de informatieve systeemvariabelen kunnen worden gemodelleerd door de informatie als argumenten door te geven tijdens het uitvoeren van de taak. Andere hebben mogelijk een equivalente functie in de hosttaal van Spark.

U-SQL-hints

U-SQL biedt verschillende syntactische manieren om hints te geven aan het queryoptimalisatieprogramma en de uitvoeringsengine:

  • Een U-SQL-systeemvariabele instellen
  • een OPTION component die is gekoppeld aan de rijensetexpressie om een gegevens- of planhint te bieden
  • een joinhint in de syntaxis van de join-expressie (bijvoorbeeld BROADCASTLEFT)

Het op kosten gebaseerde queryoptimalisatieprogramma van Spark heeft zijn eigen mogelijkheden om hints te bieden en de queryprestaties af te stemmen. Raadpleeg de bijbehorende documentatie.

Volgende stappen