Descripción del código de Apache Spark para los desarrolladores de U-SQL
Importante
Azure Data Lake Analytics se retirará el 29 de febrero de 2024. Más información sobre este anuncio.
Para el análisis de datos, su organización puede usar Azure Synapse Analytics o Microsoft Fabric.
En esta sección se proporcionan instrucciones generales sobre cómo transformar scripts de U-SQL en Apache Spark.
- Empieza con una comparación de los paradigmas de procesamiento de los dos lenguajes.
- Proporciona recomendaciones sobre cómo:
- Transformar scripts, incluidas las expresiones de conjunto de filas de U-SQL.
- Código .NET.
- Tipos de datos
- Objetos de catálogo
Descripción de los paradigmas de procesamiento y lenguaje de U-SQL y Spark
Antes de empezar a migrar scripts de U-SQL de Azure Data Lake Analytics a Spark, resulta útil comprender las filosofías generales de lenguaje y procesamiento de los dos sistemas.
U-SQL es un lenguaje de consulta declarativo parecido a SQL que utiliza un paradigma de flujo de datos y permite insertar y escalar horizontalmente de forma sencilla el código de usuario escrito en .NET (por ejemplo, C#), Python y R. Las extensiones de usuario pueden implementar expresiones sencillas o funciones definidas por el usuario, pero también pueden proporcionar al usuario la capacidad de implementar los llamados operadores definidos por el usuario, que implementan operadores personalizados para realizar transformaciones de nivel de conjunto de filas, extracciones y escritura de salida.
Spark es un marco de escalado horizontal que ofrece varios enlaces de lenguaje en Scala, Java, Python, .NET, etc., donde el código se escribe principalmente en uno de estos lenguajes, se crean abstracciones de datos llamadas conjuntos de datos distribuidos resistentes (RDD), tramas de datos y conjuntos de datos y, después, se usa un lenguaje específico de dominio (DSL) parecido a LINQ para transformarlos. También proporciona SparkSQL como sublenguaje declarativo en las abstracciones de los conjuntos de datos y tramas de datos. El Lenguaje específico de dominio proporciona dos categorías de operaciones, transformaciones y acciones. Aplicar transformaciones a las abstracciones de datos no ejecutará la transformación sino que, en su lugar, creará el plan de ejecución que se enviará para su evaluación con una acción (por ejemplo, escribir el resultado en una tabla o un archivo temporal, o imprimir el resultado).
Por tanto, al convertir un script de U-SQL en un programa de Spark, tendrá que decidir qué lenguaje quiere usar para, al menos, generar la abstracción de la trama de datos (que actualmente es la abstracción de datos usada con más frecuencia) y si quiere escribir las transformaciones declarativas de flujos de datos con DSL o SparkSQL. En algunos casos más complejos, es posible que tenga que dividir el script de U-SQL en una secuencia de Spark y en otros pasos implementados con Azure Batch o Azure Functions.
Además, Azure Data Lake Analytics ofrece U-SQL en un entorno de servicio de trabajo sin servidor donde se asignan recursos para cada trabajo, mientras que Azure Synapse Spark, Azure Databricks y Azure HDInsight ofrecen Spark en forma de servicio de clúster o con plantillas de grupo de Spark. Al transformar la aplicación, deberá tener en cuenta las implicaciones que conlleva ahora crear, cambiar el tamaño, escalar y retirar los clústeres o grupos.
Transformación de scripts de U-SQL
Los scripts de U-SQL siguen el siguiente patrón de procesamiento:
- Los datos se leen desde archivos no estructurados, mediante la instrucción
EXTRACT
, una ubicación o una especificación del conjunto de archivos, el extractor integrado o definido por el usuario, y el esquema deseado, o bien desde las tablas U-SQL (tablas administradas o externas). Se representan como un conjunto de filas. - Los conjuntos de filas se transforman en varias instrucciones de U-SQL que aplican expresiones de U-SQL a los conjuntos de filas y generan nuevos conjuntos de filas.
- Por último, los conjuntos de filas resultantes se envían a los dos archivos mediante la instrucción
OUTPUT
, que especifica las ubicaciones y un outputter integrado o definido por el usuario, o a una tabla de U-SQL.
El script se evalúa de forma diferida, lo que significa que cada paso de extracción y transformación se compone en un árbol de expresión y se evalúa globalmente (el flujo de datos).
Los programas de Spark son similares en cuanto a que se usarían conectores de Spark para leer los datos y crear las tramas de datos y, después, se aplicarían las transformaciones en las tramas de datos mediante DSL o SparkSQL de tipo LINQ, y luego se escribiría el resultado en archivos, tablas temporales de Spark, algunos tipos de lenguajes de programación o la consola.
Transformación de código .NET
El lenguaje de expresión de U-SQL es C# y ofrece varias formas de escalar horizontalmente el código .NET personalizado con funciones, operadores y agregadores definidos por el usuario.
Azure Synapse y Azure HDInsight Spark ahora admiten de forma nativa la ejecución de código de .NET con .NET para Apache Spark. Esto significa que puede reutilizar algunas o todas las funciones definidas por el usuario de .NET con Spark. Tenga en cuenta que U-SQL usa .NET Framework, mientras que .NET para Apache Spark se basa en .NET Core 3.1 o versiones posteriores.
Los operadores definidos por el usuario (UDO) de U-SQL usan el modelo de UDO de U-SQL para proporcionar una ejecución escalada horizontalmente del código del operador. Por lo tanto, los UDO tendrán que volver a escribirse en funciones definidas por el usuario para ajustarse al modelo de ejecución de Spark.
.NET para Apache Spark actualmente no admite los agregadores definidos por el usuario. Por lo tanto, los agregadores definidos por el usuario de U-SQL tendrán que traducirse a agregadores definidos por el usuario de Spark escritos en Scala.
Si no quiere aprovechar las funcionalidades de .NET para Apache Spark, tendrá que volver a escribir las expresiones en una expresión, función, agregador o conector equivalentes de Spark, Scala, Java o Python.
En cualquier caso, si tiene una gran cantidad de lógica .NET en los scripts de U-SQL, póngase en contacto con nosotros a través de su representante de cuenta de Microsoft para obtener más información.
Los detalles siguientes sirven para los distintos casos de uso de .NET y C# de los scripts de U-SQL.
Transformación de expresiones insertadas escalares de C# en U-SQL
El lenguaje de las expresiones de U-SQL es C#. Muchas de las expresiones de U-SQL insertadas escalares se implementan de forma nativa para mejorar el rendimiento, mientras que las expresiones más complejas pueden ejecutarse a través de llamadas a .NET Framework.
Spark tiene su propio lenguaje de expresiones escalares (ya sea como parte de DSL o en SparkSQL) y permite llamar a funciones definidas por el usuario escritas para el runtime de JVM, .NET o Python.
Si tiene expresiones escalares en U-SQL, primero debe buscar la expresión escalar de Spark de forma nativa más adecuada para obtener el máximo rendimiento y, después, asignar las demás expresiones en una función definida por el usuario del lenguaje del runtime de Spark que prefiera.
Tenga en cuenta que .NET y C# tienen una semántica de tipos distinta que la de los runtimes de JVM y Python y que la del DSL de Spark. Vea a continuación para obtener más información sobre las diferencias del sistema de tipos.
Transformación de funciones .NET escalares definidas por el usuario y de agregadores definidos por el usuario
U-SQL proporciona maneras de llamar a funciones de .NET escalares arbitrarias y de llamar a agregadores definidos por el usuario escritos en .NET.
Spark también ofrece compatibilidad con funciones definidas por el usuario y agregadores definidos por el usuario escritos en la mayoría de lenguajes de hospedaje a los que se puede llamar desde el DSL de Spark y SparkSQL.
Como se mencionó anteriormente, .NET para Apache Spark admite funciones definidas por el usuario escritas en .NET, pero no admite agregadores definidos por el usuario. Por lo tanto, para las funciones definidas por el usuario, se puede usar .NET para Apache Spark, mientras que los agregadores definidos por el usuario deben crearse en Scala para Spark.
Transformación de operadores definidos por el usuario (UDO)
U-SQL proporciona varias categorías de operadores definidos por el usuario (UDO), como extractores, outputters, reductores, procesadores, aplicadores y combinadores que se pueden escribir en .NET (y, hasta cierto punto, en Python y R).
Spark no ofrece el mismo modelo de extensibilidad para los operadores, pero tiene funciones equivalentes para algunos.
El equivalente de Spark a los extractores y outputters son los conectores de Spark. Para muchos extractores de U-SQL, se puede encontrar un conector equivalente en la comunidad de Spark. Para el resto, se tendrá que escribir un conector personalizado. Si el extractor de U-SQL es complejo y utiliza varias bibliotecas .NET, puede ser preferible compilar un conector en Scala que use la interoperabilidad para llamar a la biblioteca .NET que realiza el procesamiento real de los datos. En ese caso, tendrá que implementar el runtime de .NET Core en el clúster de Spark y asegurarse de que las bibliotecas .NET a las que se hace referencia son compatibles con .NET Standard 2.0.
El resto de tipos de UDO de U-SQL deberán volver a escribirse con funciones definidas por el usuario y agregadores, y la expresión DSL de Spark o SparkSQL semánticamente adecuada. Por ejemplo, un procesador se puede asignar a una selección de varias invocaciones de UDF, empaquetadas como una función que toma una trama de datos como argumento y devuelve una trama de datos.
Transformación de bibliotecas de U-SQL opcionales
U-SQL proporciona un conjunto de bibliotecas opcionales y de demostración que ofrecen Python, R, compatibilidad con JSON, XML y AVRO, así como algunas funciones de servicios de Azure AI.
Spark ofrece su propia integración de Python y R, pySpark y SparkR, respectivamente, y proporciona conectores para leer y escribir JSON, XML y AVRO.
Si necesita transformar un script que hace referencia a las bibliotecas de servicios de Azure AI, recomendamos que se ponga en contacto con nosotros a través de su representante de cuenta de Microsoft.
Transformación de valores de tipo
Dado que el sistema de tipos de U-SQL se basa en el sistema de tipos de .NET y Spark tiene su propio sistema de tipos, que se ve afectado por el enlace de lenguaje del host, tendrá que asegurarse de que los tipos en los que trabaja sean próximos y, para determinados tipos, los rangos de tipo, la precisión y la escala pueden ser ligeramente diferentes. Además, U-SQL y Spark tratan los valores null
de manera distinta.
Tipos de datos
En la tabla siguiente se proporcionan los tipos equivalentes en Spark, Scala y PySpark para los tipos de U-SQL especificados.
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) |
Para más información, vea:
Tratamiento del valor NULL
En Spark, los tipos admiten valores NULL de forma predeterminada, mientras que en U-SQL, se marca explícitamente el valor escalar, que no es de objeto, como capaz de admitir un valor NULL. Aunque Spark permite definir que una columna no admita un valor NULL, no se aplicará la restricción y podría producir un resultado incorrecto.
En Spark, NULL indica que el valor es desconocido. Un valor NULL de Spark es diferente de cualquier valor, incluido el mismo valor. Las comparaciones entre dos valores NULL de Spark, o entre un valor NULL y cualquier otro valor, devuelven un resultado desconocido porque el valor de cada NULL es desconocido.
Este comportamiento es diferente de U-SQL, que sigue la semántica de C#, donde null
es diferente de cualquier valor, pero es igual a sí mismo.
Por tanto, una instrucción SELECT
de SparkSQL que usa WHERE column_name = NULL
devuelve cero filas aunque haya valores NULL en column_name
, mientras que en U-SQL, devolvería las filas en las que el elemento column_name
está establecido en null
. De igual forma, una instrucción SELECT
de Spark que usa WHERE column_name != NULL
devuelve cero filas aunque haya valores que no sean NULL en column_name
, mientras que en U-SQL, devolvería las filas cuyo valor no sea NULL. Por tanto, si quiere la semántica de comprobación de valores NULL de U-SQL, debe usar isnull e isnotnull respectivamente (o su equivalente de DSL).
Transformación de objetos de catálogo de U-SQL
Una diferencia importante es que los scripts de U-SQL pueden utilizar sus objetos de catálogo, muchos de los cuales no tienen ningún equivalente de Spark directo.
Spark proporciona compatibilidad con los conceptos de metastore de Hive, principalmente las bases de datos, tablas y vistas, por lo que se pueden asignar esquemas y bases de datos de U-SQL a bases de datos de Hive, y tablas de U-SQL a tablas de Spark (vea Traslado de los datos almacenados en tablas U-SQL), pero no admite funciones con valores de tabla (TVF), procedimientos almacenados, ensamblados de U-SQL, orígenes de datos externos, etc.
Los objetos de código de U-SQL, como vistas, TVF, procedimientos almacenados y ensamblados, se pueden modelar a través de las funciones de código y las bibliotecas de Spark, y se puede hacer referencia a ellos mediante la función del lenguaje de host y los mecanismos de abstracción de procedimientos (por ejemplo, mediante la importación de módulos de Python o haciendo referencia a funciones de Scala).
Si el catálogo de U-SQL se ha usado para compartir datos y objetos de código entre proyectos y equipos, se deben usar mecanismos equivalentes para compartir (por ejemplo, Maven para objetos de código de uso compartido).
Transformación de expresiones de conjunto de filas de U-SQL y expresiones escalares basadas en SQL
El lenguaje principal de U-SQL está transformando los conjuntos de filas y se basa en SQL. A continuación se muestra una lista no exhaustiva de las expresiones de conjunto de filas más comunes que se ofrecen en U-SQL:
SELECT
/FROM
/WHERE
/GROUP BY
+Aggregates+HAVING
/ORDER BY
+FETCH
Expresiones
INNER
/OUTER
/CROSS
/SEMI
JOIN
Expresiones
CROSS
/OUTER
APPLY
Expresiones
PIVOT
/UNPIVOT
Constructor de conjunto de filas
VALUES
Expresiones de conjunto
UNION
/OUTER UNION
/INTERSECT
/EXCEPT
Además, U-SQL proporciona varias expresiones escalares basadas en SQL, como
- expresiones
OVER
basadas en ventanas - diversos agregadores integrados y funciones de categoría (
SUM
,FIRST
etc.). - Aquí se muestran algunas de las expresiones SQL escalares más conocidas:
CASE
,LIKE
, (NOT
)IN
,AND
,OR
, etc.
Spark ofrece expresiones equivalentes en formato DSL y SparkSQL para la mayoría de estas expresiones. Algunas de las expresiones que no se admiten de forma nativa en Spark tendrán que reescribirse mediante una combinación de expresiones de Spark nativas y los patrones semánticamente equivalentes. Por ejemplo, OUTER UNION
tendrá que traducirse en la combinación equivalente de proyecciones y uniones.
Debido al control distinto de los valores NULL, una combinación de U-SQL siempre coincidirá con una fila si las dos columnas que se comparan contienen un valor NULL, mientras que una combinación en Spark no coincidirá con estas columnas a menos que se agreguen comprobaciones de valores NULL explícitas.
Transformación de otros conceptos de U-SQL
U-SQL también ofrece una variedad de otros conceptos y características, como consultas federadas en bases de datos de SQL Server, parámetros, escalares y variables de expresión lambda, variables del sistema y sugerencias de OPTION
.
Consultas federadas en bases de datos o tablas externas de SQL Server
U-SQL proporciona tablas externas y de origen de datos, así como consultas directas en Azure SQL Database. Aunque Spark no ofrece las mismas abstracciones de objeto, proporciona un Conector de Spark para Azure SQL Database que se puede usar para consultar bases de datos SQL.
Parámetros y variables de U-SQL
Los parámetros y las variables de usuario tienen conceptos equivalentes en Spark y sus lenguajes de hospedaje.
En Scala, por ejemplo, se puede definir una variable con la palabra clave var
:
var x = 2 * 3;
println(x)
Las variables del sistema de U-SQL (variables que empiezan por @@
) se pueden dividir en dos categorías:
- Variables del sistema configurables que se pueden establecer en valores específicos para afectar al comportamiento de los scripts.
- Variables del sistema informativas que consultan información de nivel de trabajo y de sistema.
La mayoría de variables del sistema configurables no tienen ningún equivalente directo en Spark. Algunas de las variables del sistema informativas se pueden modelar pasando la información como argumentos durante la ejecución del trabajo, mientras que otras pueden tener una función equivalente en el lenguaje de hospedaje de Spark.
Sugerencias de U-SQL
U-SQL ofrece varias maneras sintácticas de proporcionar sugerencias al optimizador de consultas y al motor de ejecución:
- Establecer una variable del sistema de U-SQL.
- Una cláusula
OPTION
asociada a la expresión de conjunto de filas para proporcionar una sugerencia de datos o de plan. - Una sugerencia de combinación en la sintaxis de la expresión de combinación (por ejemplo,
BROADCASTLEFT
).
El optimizador de consultas basado en el costo de Spark tiene sus propias funciones para proporcionar sugerencias y ajustar el rendimiento de las consultas. Consulte la documentación correspondiente.
Pasos siguientes
- Descripción de los formatos de datos de Spark para desarrolladores de U-SQL
- .NET para Apache Spark
- Actualización de las soluciones de análisis de macrodatos de Azure Data Lake Storage Gen1 a Azure Data Lake Storage Gen2
- Transformación de datos mediante la actividad de Spark en Azure Data Factory
- Transformación de datos mediante la actividad de Hive de Hadoop en Azure Data Factory
- ¿Qué es Apache Spark en Azure HDInsight