Comprendre le code Apache Spark pour les développeurs U-SQL
Important
Azure Data Lake Analytics a été mis hors service le 29 février 2024. Découvrez-en plus avec cette annonce.
Pour l'analyse des données, votre organisation peut utiliser Azure Synapse Analytics ou Microsoft Fabric.
Cette section fournit des conseils de haut niveau sur la transformation des scripts U-SQL en Apache Spark.
- Il commence par une comparaison des paradigmes de traitement des deux langages informatiques.
- Fournit des conseils sur la façon de :
- Transformer des scripts, y compris des expressions d’ensemble de lignes d’U-SQL
- Code .NET
- Types de données
- Objets de catalogue
Comprendre les paradigmes de langage et de traitement U-SQL et Spark
Avant de commencer à migrer les scripts U-SQL d’Azure Data Lake Analytics vers Spark, il est utile de comprendre le langage général et les philosophies de traitement des deux systèmes.
U-SQL est un langage de requête déclaratif de type SQL qui utilise un paradigme de flux de données et vous permet d’incorporer et d’effectuer facilement un scale-out du code utilisateur écrit dans écrit en.NET (par exemple C#), Python et R. Les extensions utilisateur peuvent implémenter des expressions simples ou des fonctions définies par l’utilisateur, mais elles peuvent également fournir à l’utilisateur la possibilité d’implémenter des opérateurs définis par l’utilisateur qui implémentent des opérateurs personnalisés pour effectuer des transformations au niveau de l’ensemble de lignes, des extractions et l’écriture de la sortie.
Spark est une infrastructure Scale-out qui offre plusieurs liaisons de langage Scala, Java, Python, .NET, etc. et dans laquelle vous écrivez principalement votre code dans l’un de ces langages, créez des abstractions de données appelées jeux de données distribués résilients (RDD), des trames et jeux de données, puis utilisez un langage spécifique à un domaine (DSL) de type LINQ pour les transformer. Il fournit également SparkSQL sous la forme d’un sous-langage déclaratif sur les abstractions de trames et jeux de données. Le DSL prévoit deux catégories d’opérations, de transformations et d’actions. L’application de transformations aux abstractions de données n’exécutera pas la transformation, mais générera à la place le plan d’exécution qui sera soumis pour évaluation avec une action (par exemple, en écrivant le résultat dans une table ou un fichier temporaire, ou en imprimant le résultat).
Ainsi, lors de la traduction d’un script U-SQL en programme Spark, vous devrez décider quel langage vous voulez utiliser pour générer au moins l’abstraction de la trame de données (qui est actuellement la plus fréquemment utilisée) et si vous souhaitez écrire les transformations déclaratives de flux de données en utilisant DSL ou SparkSQL. Dans certains cas plus complexes, vous devrez peut-être fractionner votre script U-SQL en une séquence de Spark et d’autres étapes implémentées avec Azure Batch ou Azure Functions.
En outre, Azure Data Lake Analytics offre U-SQL dans un environnement de service de travail serverless où les ressources sont allouées pour chaque travail, tandis qu’Azure Synapse Spark, Azure Databricks et Azure HDInsight offrent Spark sous forme d’un service de cluster ou via des modèles de pool Spark. Quand vous transformez votre application, vous devez prendre en compte les implications de la création, du dimensionnement, de la mise à l’échelle et de la désactivation des clusters ou pools.
Transformer des scripts U-SQL
Les scripts U-SQL suivent le modèle de traitement suivant :
- Les données sont lues à partir de fichiers non structurés, à l’aide de l’instruction
EXTRACT
, une spécification d’emplacement ou de jeu de fichiers, de l’extracteur intégré ou défini par l’utilisateur et du schéma souhaité, ou à partir de tables U-SQL (tables managées ou externes). Elle est représentée sous forme d’ensemble de lignes. - Les ensembles de lignes sont transformés en plusieurs instructions U-SQL qui appliquent des expressions U-SQL à ces ensembles et en produisent de nouveaux.
- Enfin, les ensembles de lignes résultants sont générés soit dans des fichiers à l’aide de l’instruction
OUTPUT
qui spécifie les emplacements et d’un générateur de sortie intégré ou défini par l’utilisateur, soit dans une table U-SQL.
Le script est évalué de manière différée, ce qui signifie que chaque étape d’extraction et de transformation est composée dans une arborescence de l’expression et évaluée globalement (le dataflow).
Les programmes Spark sont similaires en ce sens que vous utiliseriez des connecteurs Spark pour lire les données et créer les trames de données, puis appliqueriez les transformations sur le trames de données en utilisant soit le DSL de type LINQ soit SparkSQL, pour enfin écrire le résultat dans des fichiers, des tables Spark temporaires, certains types de langages de programmation ou la console.
Transformer le code .NET
Le langage d’expression de U-SQL est C# et offre différentes façons d’effectuer un scale-out de code .NET personnalisé avec des fonctions définies par l’utilisateur, des opérateurs définis par l’utilisateur et des agrégateurs définis par l’utilisateur.
Azure Synapse et Azure HDInsight Spark prennent désormais en charge l’exécution en mode natif du code .NET avec .NET pour Apache Spark. Cela signifie que vous pouvez potentiellement réutiliser certaines ou toutes vos fonctions définies par l’utilisateur .NET avec Spark. Notez que U-SQL utilise .NET Framework, alors que .NET pour Apache Spark est basé sur .NET Core 3.1 ou version ultérieure.
Les opérateurs U-SQL définis par l’utilisateur (UDO) utilisent le modèle UDO U-SQL pour fournir une exécution avec scale-out du code de l’opérateur. Par conséquent, les opérateurs UDO doivent être réécrits dans des fonctions définies par l’utilisateur pour s’adapter au modèle d’exécution Spark.
.NET pour Apache Spark ne prend actuellement pas en charge les agrégateurs définis par l’utilisateur. Par conséquent, les agrégateurs définis par l’utilisateur U-SQL doivent être traduits en agrégateurs définis par l’utilisateur Spark écrits en Scala.
Si vous ne souhaitez pas tirer parti des fonctionnalités .NET pour Apache Spark, vous devez réécrire vos expressions dans une expression Spark, Scala, Java ou Python équivalente, fonction, agrégateur ou connecteur.
Dans tous les cas, si vous avez une grande quantité de logique .NET dans vos scripts U-SQL, veuillez nous contacter par le biais de votre représentant de compte Microsoft pour obtenir de l’aide.
Les informations suivantes concernent les différents cas d’utilisation de .NET et C# dans les scripts U-SQL.
Transformer des expressions U-SQL C# inlined scalaires
Le langage d’expression de U-SQL est C#. La plupart des expressions U-SQL inline scalaires sont implémentées en mode natif pour améliorer les performances, tandis que des expressions plus complexes peuvent être exécutées via l’appel au .NET Framework.
Spark possède son propre langage d’expression scalaire (dans le cadre du DSL ou de SparkSQL) et permet l’appel de fonctions définies par l’utilisateur écrites pour le runtime JVM, .NET ou Python.
Si vous avez des expressions scalaires en U-SQL, vous devez d’abord trouver l’expression scalaire Spark la plus appropriée en mode natif pour obtenir les meilleures performances, puis mapper les autres expressions dans une fonction définie par l’utilisateur du langage de runtime Spark de votre choix.
Sachez que .NET et C# ont une sémantique de type différente de celle des runtimes JVM et Python et du DSL de Spark. Voir ci-dessous pour plus d’informations sur les différences entre les types de systèmes.
Transformer des fonctions .NET scalaires et agrégateurs définis par l’utilisateur
U-SQL permet d’appeler des fonctions .NET scalaires arbitraires ainsi que des agrégateurs définis par l’utilisateur écrits en .NET.
Spark offre également la prise en charge des fonctions et agrégateurs définis par l’utilisateur écrits dans la plupart de ses langages d’hébergement qui peuvent être appelés à partir du DSL de Spark et de SparkSQL.
Comme mentionné ci-dessus, .NET pour Apache Spark prend en charge les fonctions définies par l’utilisateur écrites dans .NET, mais ne prend pas en charge les agrégateurs définis par l’utilisateur. Par conséquent, .NET pour Apache Spark peut être utilisé pour les fonctions définies par l’utilisateur, tandis que les agrégateurs définis par l’utilisateur doivent être créés dans Scala pour Spark.
Transformer des opérateurs définis par l’utilisateur (UDO)
U-SQL fournit plusieurs catégories d’opérateurs définis par l’utilisateur (UDO), tels que des extracteurs, des générateurs de sortie, des réducteurs, des processeurs, des applicateurs et des combinateurs qui peuvent être écrits en .NET (et, dans une certaine mesure, dans Python et R).
Spark n’offre pas le même modèle d’extensibilité pour les opérateurs, mais a des fonctionnalités équivalentes pour certains.
L’équivalent Spark des extracteurs et des générateurs de sortie est les connecteurs Spark. Pour de nombreux extracteurs U-SQL, vous pouvez trouver un connecteur équivalent dans la communauté Spark. Pour d’autres, vous devez écrire un connecteur personnalisé. Si l’extracteur U-SQL est complexe et utilise plusieurs bibliothèques .NET, il peut être préférable de créer un connecteur en Scala qui utilise l’interopérabilité pour appeler la bibliothèque .NET qui effectue le traitement réel des données. Dans ce cas, vous devez déployer le runtime .NET Core sur le cluster Spark et vous assurer que les bibliothèques .NET référencées sont conformes à .NET Standard 2.0.
Les autres types d’UDO U-SQL devront être réécrits à l’aide de fonctions et d’agrégateurs définis par l’utilisateur et de l’expression DLS de Spark ou SparkSQL sémantiquement appropriée. Par exemple, un processeur peut être mappé à un SELECT de différents appels UDF, empaquetés en tant que fonction qui prend un dataframe en tant qu’argument et retourne un dataframe.
Transformer les bibliothèques facultatives U-SQL
U-SQL fournit un ensemble de bibliothèques facultatives et de démonstration qui offrent la prise en charge de Python, R, JSON, XML et AVRO et certaines fonctionnalités Azure AI services.
Spark offre sa propre intégration de Python et R, pySpark et SparkR respectivement, et fournit des connecteurs pour lire et écrire JSON, XML et AVRO.
Si vous devez transformer un script référençant les bibliothèques Azure AI services, nous vous recommandons de nous contacter via votre représentant de compte Microsoft.
Transformer les valeurs typées
Comme le système de type U-SQL est basé sur le système de type de .NET et que Spark a son propre système de type qui est impacté par la liaison du langage hôte, vous devrez vous assurer que les types sur lesquels vous opérez sont proches et pour certains types, les plages de type, la précision et/ou l'échelle peuvent être légèrement différentes. En outre, U-SQL et Spark traitent les valeurs null
différemment.
Types de données
Le tableau suivant donne les types équivalents en Spark, Scala et PySpark pour les types U-SQL donnés.
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) |
Pour plus d’informations, consultez l’article suivant :
Traitement de la valeur NULL
En Spark, les types par défaut autorisent les valeurs NULL alors qu’en U-SQL, vous marquez explicitement une valeur scalaire qui ne représente pas un objet comme pouvant accepter la valeur Null. Bien que Spark vous permette de définir une colonne comme n’acceptant pas la valeur Null, cela n’appliquera pas la contrainte et peut conduire à un résultat erroné.
En Spark, NULL indique que la valeur est inconnue. Une valeur NULL Spark est différente de toute valeur, y compris elle-même. Les comparaisons entre deux valeurs NULL Spark, ou entre une valeur NULL et toute autre valeur, retournent le résultat Inconnu, car la valeur de chaque NULL est inconnue.
Ce comportement est différent d’U-SQL, qui suit la sémantique C# où null
est différente de toute valeur, mais égale à elle-même.
Ainsi, une instruction SELECT
SparkSQL qui utilise WHERE column_name = NULL
retourne zéro ligne, même s’il existe des valeurs NULL dans column_name
, alors qu’en U-SQL, elle retourne les lignes où column_name
est défini sur null
. De même, une instruction SELECT
Spark qui utilise WHERE column_name != NULL
retourne zéro ligne, même s’il existe des valeurs non Null dans column_name
, alors qu’en U-SQL, elle retourne les lignes qui contiennent les valeurs non Null. Par conséquent, si vous souhaitez la sémantique U-SQL de vérification des valeurs Null, vous devez utiliser isnull) et isnotnull respectivement (ou leur équivalent DSL).
Transformer des objets de catalogue U-SQL
L’une des principales différences réside dans le fait que les scripts U-SQL peuvent utiliser ses objets de catalogue, dont un grand nombre n’ont pas d’équivalent Spark direct.
Spark assure la prise en charge des concepts du magasin Hive Meta, principalement des bases de données, des tables et des affichages, de sorte que vous pouvez mapper des bases de données et des schémas U-SQL à des bases de données Hive, et des tables U-SQL à des tables Spark (voir Déplacement de données stockées dans des tables U-SQL), mais n’offre aucune prise en charge des Fonctions table (TVF), des procédures stockées, des assemblys U-SQL, des sources de données externes, etc.
Les objets de code U-SQL, tels que les affichages, les TVF, les procédures stockées et les assemblys, peuvent être modélisés à l’aide de fonctions de code et de bibliothèques en Spark et référencés en utilisant les mécanismes d’abstraction de fonctions et de procédures du langage hôte (par exemple, en important des modules Python ou en faisant référence à des fonctions Scala).
Si le catalogue U-SQL a été utilisé pour partager des données et des objets de code entre des projets et des équipes, les mécanismes équivalents doivent être utilisés pour le partage (par exemple, Maven pour le partage d’objets de code).
Transformer des expressions d’ensemble de lignes U-SQL et des expressions scalaires basées sur SQL
Le langage de base d’U-SQL transforme des ensembles de lignes et repose sur SQL. Voici une liste non exhaustive des expressions d’ensemble de lignes les plus courantes proposées dans U-SQL :
SELECT
/FROM
/WHERE
/GROUP BY
+Aggregates+HAVING
/ORDER BY
+FETCH
Expressions
INNER
/OUTER
/CROSS
/SEMI
JOIN
Expressions
CROSS
/OUTER
APPLY
Expressions
PIVOT
/UNPIVOT
Constructeur d’ensemble de lignes
VALUES
Expressions définies
UNION
/OUTER UNION
/INTERSECT
/EXCEPT
En outre, U-SQL fournit différentes expressions scalaires basées sur SQL, telles que
- des expressions de fenêtrage
OVER
- différents agrégateurs intégrés et fonctions de classement (
SUM
,FIRST
etc.) - Voici quelques-unes des expressions scalaires SQL les plus familières :
CASE
,LIKE
, (NOT
)IN
,AND
,OR
, etc.
Spark propose des expressions équivalentes dans sa forme DSL et SparkSQL pour la plupart de ces expressions. Certaines des expressions non prises en charge en mode natif en Spark devront être réécrites à l’aide d’une combinaison des expressions Spark natives et des modèles sémantiquement équivalents. Par exemple, OUTER UNION
doit être traduit dans la combinaison équivalente de projections et d’unions.
En raison de la gestion différente des valeurs NULL, une jointure U-SQL correspond toujours à une ligne si les deux colonnes comparées contiennent une valeur NULL, tandis qu’une jointure dans Spark ne correspond pas à ces colonnes, sauf si des vérifications null explicites sont ajoutées.
Transformer d’autres concepts U-SQL
U-SQL offre également diverses autres fonctionnalités et concepts, tels que les requêtes fédérées sur les bases de données SQL Server, les paramètres, les variables scalaires et les variables d’expression lambda, les variables système, les indicateurs de OPTION
.
Requêtes fédérées par rapport à des bases de données SQL Server/tables externes
U-SQL fournit une source de données et des tables externes, ainsi que des requêtes directes par rapport à Azure SQL Database. Même si Spark n’offre pas les mêmes abstractions d’objets, il fournit connecteur Spark pour Azure SQL Database qui peut être utilisé pour interroger des bases de données SQL.
Paramètres et variables U-SQL
Les paramètres et les variables utilisateur ont des concepts équivalents en Spark et dans leurs langages d’hébergement.
Par exemple, en Scala, vous pouvez définir une variable avec le mot clé var
:
var x = 2 * 3;
println(x)
Les variables système d’U-SQL (variables commençant par @@
) peuvent être divisées en deux catégories :
- Variables système paramétrables qui peuvent être définies sur des valeurs spécifiques pour avoir un impact sur le comportement des scripts
- Variables système d’information qui interrogent les informations au niveau du système et du travail
La plupart des variables système paramétrables n’ont pas d’équivalent direct en Spark. Certaines des variables système d’information peuvent être modélisées en passant les informations en tant qu’arguments lors de l’exécution des tâches. D’autres peuvent avoir une fonction équivalente dans le langage d’hébergement de Spark.
Conseils U-SQL
U-SQL offre plusieurs façons syntaxiques de fournir des conseils à l’optimiseur de requête et au moteur d’exécution :
- Paramétrage d’une variable système U-SQL
- une clause
OPTION
associée à l’expression de l’ensemble de lignes pour fournir un conseil relatif aux données ou au plan - un conseil de jointure dans la syntaxe de l’expression de jointure (par exemple,
BROADCASTLEFT
)
L’optimiseur de requête basé sur les coûts de Spark possède ses propres fonctionnalités pour fournir des conseils et optimiser les performances des requêtes. Reportez-vous à la documentation correspondante.
Étapes suivantes
- Comprendre les formats de données Spark pour les développeurs U-SQL
- .NET pour Apache Spark
- Mettre à niveau vos solutions d’analytique de Big Data d’Azure Data Lake Storage Gen1 vers Azure Data Lake Storage Gen2
- Transformer des données à l’aide d’une activité Spark dans Azure Data Factory
- Transformer des données à l’aide d’une activité Hadoop Hive dans Azure Data Factory
- Qu’est-ce qu’Apache Spark dans Azure HDInsight