Partilhar via


Compreender o código Apache Spark para desenvolvedores U-SQL

Importante

O Azure Data Lake Analytics foi desativado em 29 de fevereiro de 2024. Saiba mais com este anúncio.

Para análise de dados, sua organização pode usar o Azure Synapse Analytics ou o Microsoft Fabric.

Esta seção fornece orientação de alto nível sobre como transformar scripts U-SQL para Apache Spark.

Compreender os paradigmas de processamento e linguagem U-SQL e Spark

Antes de começar a migrar os scripts U-SQL do Azure Data Lake Analytics para o Spark, é útil entender a linguagem geral e as filosofias de processamento dos dois sistemas.

U-SQL é uma linguagem de consulta declarativa semelhante ao SQL que usa um paradigma de fluxo de dados e permite que você incorpore e dimensione facilmente o código do usuário escrito em .NET (por exemplo, C#), Python e R. As extensões de usuário podem implementar expressões simples ou funções definidas pelo usuário, mas também podem fornecer ao usuário a capacidade de implementar os chamados operadores definidos pelo usuário que implementam operadores personalizados para executar transformações de nível de conjunto de linhas, extrações e saída de gravação.

O Spark é uma estrutura de expansão que oferece várias ligações de linguagem em Scala, Java, Python, .NET etc., onde você escreve principalmente seu código em uma dessas linguagens, cria abstrações de dados chamadas conjuntos de dados distribuídos resilientes (RDD), dataframes e conjuntos de dados e, em seguida, usa uma linguagem específica de domínio (DSL) semelhante a LINQ para transformá-los. Ele também fornece SparkSQL como uma sublinguagem declarativa no dataframe e abstrações de conjunto de dados. O DSL fornece duas categorias de operações, transformações e ações. A aplicação de transformações às abstrações de dados não executará a transformação, mas criará o plano de execução que será enviado para avaliação com uma ação (por exemplo, gravar o resultado em uma tabela ou arquivo temporário ou imprimir o resultado).

Assim, ao traduzir um script U-SQL para um programa Spark, você terá que decidir qual linguagem deseja usar para, pelo menos, gerar a abstração do quadro de dados (que é atualmente a abstração de dados usada com mais freqüência) e se deseja escrever as transformações declarativas de fluxo de dados usando DSL ou SparkSQL. Em alguns casos mais complexos, talvez seja necessário dividir seu script U-SQL em uma sequência do Spark e outras etapas implementadas com o Azure Batch ou o Azure Functions.

Além disso, o Azure Data Lake Analytics oferece U-SQL em um ambiente de serviço de trabalho sem servidor onde os recursos são alocados para cada trabalho, enquanto o Azure Synapse Spark, o Azure Databricks e o Azure HDInsight oferecem o Spark na forma de um serviço de cluster ou com os chamados modelos de pool do Spark. Ao transformar seu aplicativo, você terá que levar em conta as implicações de criar, dimensionar, dimensionar e desativar os clusters ou pools.

Transformar scripts U-SQL

Os scripts U-SQL seguem o seguinte padrão de processamento:

  1. Os dados são lidos de arquivos não estruturados, usando a EXTRACT instrução, uma especificação de local ou conjunto de arquivos e o extrator interno ou definido pelo usuário e o esquema desejado, ou de tabelas U-SQL (tabelas gerenciadas ou externas). É representado como um conjunto de linhas.
  2. Os conjuntos de linhas são transformados em várias instruções U-SQL que aplicam expressões U-SQL aos conjuntos de linhas e produzem novos conjuntos de linhas.
  3. Finalmente, os conjuntos de linhas resultantes são enviados para arquivos usando a OUTPUT instrução que especifica o(s) local(is) e um outputter interno ou definido pelo usuário, ou em uma tabela U-SQL.

O script é avaliado preguiçosamente, o que significa que cada etapa de extração e transformação é composta em uma árvore de expressão e avaliada globalmente (o fluxo de dados).

Os programas Spark são semelhantes na medida em que você usaria conectores Spark para ler os dados e criar os dataframes, em seguida, aplicar as transformações nos dataframes usando o DSL LINQ ou SparkSQL e, em seguida, gravar o resultado em arquivos, tabelas temporárias do Spark, alguns tipos de linguagem de programação ou o console.

Transformar código .NET

A linguagem de expressão do U-SQL é C# e oferece várias maneiras de expandir o código .NET personalizado com funções definidas pelo usuário, operadores definidos pelo usuário e agregadores definidos pelo usuário.

O Azure Synapse e o Azure HDInsight Spark agora oferecem suporte nativo à execução de código .NET com .NET para Apache Spark. Isso significa que você pode potencialmente reutilizar algumas ou todas as suas funções definidas pelo usuário do .NET com o Spark. Observe que o U-SQL usa o .NET Framework enquanto o .NET para Apache Spark é baseado no .NET Core 3.1 ou posterior.

Os operadores definidos pelo usuário (UDOs) do U-SQL estão usando o modelo U-SQL UDO para fornecer execução dimensionada do código do operador. Assim, os UDOs terão que ser reescritos em funções definidas pelo usuário para se encaixarem no modelo de execução do Spark.

O .NET para Apache Spark atualmente não suporta agregadores definidos pelo usuário. Assim, os agregadores U-SQL definidos pelo usuário terão que ser traduzidos em agregadores definidos pelo usuário do Spark escritos em Scala.

Se você não quiser aproveitar os recursos do .NET para Apache Spark, terá que reescrever suas expressões em uma expressão, função, agregador ou conector equivalente do Spark, Scala, Java ou Python.

Em qualquer caso, se você tiver uma grande quantidade de lógica .NET em seus scripts U-SQL, entre em contato conosco por meio de seu representante da Conta da Microsoft para obter mais orientações.

Os detalhes a seguir são para os diferentes casos de usos de .NET e C# em scripts U-SQL.

Transformar expressões escalares inline U-SQL C#

A linguagem de expressão do U-SQL é C#. Muitas das expressões U-SQL escalares embutidas são implementadas nativamente para melhorar o desempenho, enquanto expressões mais complexas podem ser executadas por meio de chamadas para o .NET framework.

O Spark tem sua própria linguagem de expressão escalar (como parte da DSL ou no SparkSQL) e permite chamar para funções definidas pelo usuário escritas para o tempo de execução da JVM, .NET ou Python.

Se você tiver expressões escalares em U-SQL, primeiro deverá encontrar a expressão escalar Spark nativamente mais apropriada para obter o máximo desempenho e, em seguida, mapear as outras expressões em uma função definida pelo usuário da linguagem de tempo de execução do Spark de sua escolha.

Lembre-se de que o .NET e o C# têm semânticas de tipo diferentes dos tempos de execução da JVM e Python e da DSL do Spark. Veja abaixo mais detalhes sobre as diferenças do sistema de tipos.

Transforme funções escalares .NET definidas pelo usuário e agregadores definidos pelo usuário

O U-SQL fornece maneiras de chamar funções .NET escalares arbitrárias e chamar agregadores definidos pelo usuário escritos em .NET.

O Spark também oferece suporte para funções definidas pelo usuário e agregadores definidos pelo usuário escritos na maioria de suas linguagens de hospedagem que podem ser chamadas a partir do DSL e SparkSQL do Spark.

Como mencionado acima, o .NET para Apache Spark suporta funções definidas pelo usuário escritas em .NET, mas não suporta agregadores definidos pelo usuário. Portanto, para funções definidas pelo usuário, o .NET para Apache Spark pode ser usado, enquanto os agregadores definidos pelo usuário precisam ser criados no Scala for Spark.

Transformar operadores definidos pelo usuário (UDOs)

O U-SQL fornece várias categorias de operadores definidos pelo usuário (UDOs), como extratores, outputters, redutores, processadores, aplicadores e combinadores que podem ser escritos em .NET (e - até certo ponto - em Python e R).

O Spark não oferece o mesmo modelo de extensibilidade para operadores, mas tem recursos equivalentes para alguns.

O Spark equivalente a extratores e saídas são conectores Spark. Para muitos extratores U-SQL, você pode encontrar um conector equivalente na comunidade Spark. Para outros, você terá que escrever um conector personalizado. Se o extrator U-SQL for complexo e fizer uso de várias bibliotecas .NET, pode ser preferível criar um conector no Scala que use interoperabilidade para chamar a biblioteca .NET que faz o processamento real dos dados. Nesse caso, você terá que implantar o tempo de execução do .NET Core no cluster do Spark e certificar-se de que as bibliotecas .NET referenciadas são compatíveis com o .NET Standard 2.0.

Os outros tipos de UDOs U-SQL precisarão ser reescritos usando funções e agregadores definidos pelo usuário e a expressão Spark DLS ou SparkSQL semanticamente apropriada. Por exemplo, um processador pode ser mapeado para um SELECT de várias invocações UDF, empacotado como uma função que usa um dataframe como um argumento e retorna um dataframe.

Transforme as bibliotecas opcionais do U-SQL

O U-SQL fornece um conjunto de bibliotecas opcionais e de demonstração que oferecem suporte a Python, R, JSON, XML, AVRO e alguns recursos de serviços de IA do Azure.

O Spark oferece sua própria integração Python e R, pySpark e SparkR, respectivamente, e fornece conectores para ler e escrever JSON, XML e AVRO.

Se você precisar transformar um script fazendo referência às bibliotecas de serviços de IA do Azure, recomendamos entrar em contato conosco por meio de seu representante da Conta da Microsoft.

Transformar valores digitados

Como o sistema de tipos do U-SQL é baseado no sistema de tipos .NET e o Spark tem seu próprio sistema de tipos que é afetado pela vinculação de idioma do host, você terá que se certificar de que os tipos em que você está operando estão próximos e, para certos tipos, os intervalos de tipos, a precisão e/ou a escala podem ser ligeiramente diferentes. Além disso, o U-SQL e o Spark tratam null os valores de forma diferente.

Tipos de dados

A tabela a seguir fornece os tipos equivalentes em Spark, Scala e PySpark para os tipos U-SQL fornecidos.

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 obter mais informações, consulte:

Tratamento de NULL

No Spark, os tipos por padrão permitem valores NULL, enquanto no U-SQL, você marca explicitamente escalar, não-objeto como anulável. Embora o Spark permita que você defina uma coluna como não anulável, ele não imporá a restrição e poderá levar a um resultado errado.

No Spark, NULL indica que o valor é desconhecido. Um valor Spark NULL é diferente de qualquer valor, incluindo ele mesmo. Comparações entre dois valores Spark NULL, ou entre um valor NULL e qualquer outro valor, retornam desconhecido porque o valor de cada NULL é desconhecido.

Esse comportamento é diferente do U-SQL, que segue a semântica C# onde null é diferente de qualquer valor, mas igual a si mesmo.

Assim, uma instrução SparkSQL SELECT que usa WHERE column_name = NULL retorna zero linhas mesmo se houver valores NULL no column_name, enquanto no U-SQL, ele retornaria as linhas onde column_name está definido como null. Da mesma forma, uma instrução Spark SELECT que usa WHERE column_name != NULL retorna zero linhas mesmo se houver valores não nulos no column_name, enquanto no U-SQL, ele retornaria as linhas que têm não-nulo. Assim, se você quiser a semântica de verificação nula U-SQL, você deve usar isnull e isnotnull respectivamente (ou seu equivalente DSL).

Transformar objetos de catálogo U-SQL

Uma grande diferença é que os scripts U-SQL podem fazer uso de seus objetos de catálogo, muitos dos quais não têm equivalente direto ao Spark.

O Spark fornece suporte para os conceitos de armazenamento Meta do Hive, principalmente bancos de dados, tabelas e exibições, para que você possa mapear bancos de dados e esquemas U-SQL para bancos de dados Hive e tabelas U-SQL para tabelas Spark (consulte Movendo dados armazenados em tabelas U-SQL), mas não tem suporte para funções com valor de tabela (TVFs), procedimentos armazenados, assemblies U-SQL, fontes de dados externas, etc.

Os objetos de código U-SQL, como views, TVFs, stored procedures e assemblies, podem ser modelados por meio de funções de código e bibliotecas no Spark e referenciados usando a função da linguagem host e mecanismos de abstração processual (por exemplo, através da importação de módulos Python ou referência a funções Scala).

Se o catálogo U-SQL tiver sido usado para compartilhar dados e objetos de código entre projetos e equipes, mecanismos equivalentes para compartilhamento deverão ser usados (por exemplo, Maven para compartilhar objetos de código).

Transformar expressões de conjunto de linhas U-SQL e expressões escalares baseadas em SQL

A linguagem principal do U-SQL é transformar conjuntos de linhas e é baseada em SQL. A seguir está uma lista não exaustiva das expressões de conjunto de linhas mais comuns oferecidas no U-SQL:

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

  • INNER/OUTER/CROSS/SEMIJOIN expressões

  • CROSS/OUTERAPPLY expressões

  • PIVOT/UNPIVOT expressões

  • VALUES rowset construtor

  • Definir expressões UNION/OUTER UNION/INTERSECT/EXCEPT

Além disso, o U-SQL fornece várias expressões escalares baseadas em SQL, como

  • OVER expressões de janela
  • vários agregadores integrados e funções de classificação (SUM, FIRST etc.)
  • Algumas das expressões escalares SQL mais familiares: CASE, LIKE, (NOT) IN, ANDOR , etc.

O Spark oferece expressões equivalentes em seu formato DSL e SparkSQL para a maioria dessas expressões. Algumas das expressões não suportadas nativamente no Spark terão que ser reescritas usando uma combinação das expressões nativas do Spark e padrões semanticamente equivalentes. Por exemplo, OUTER UNION terá de ser traduzido na combinação equivalente de projeções e uniões.

Devido ao tratamento diferente de valores NULL, uma junção U-SQL sempre corresponderá a uma linha se ambas as colunas que estão sendo comparadas contiverem um valor NULL, enquanto uma junção no Spark não corresponderá a essas colunas, a menos que verificações nulas explícitas sejam adicionadas.

Transformar outros conceitos U-SQL

O U-SQL também oferece vários outros recursos e conceitos, como consultas federadas em bancos de dados do SQL Server, parâmetros, variáveis de expressão escalar e lambda, variáveis de sistema, OPTION dicas.

Consultas federadas em bancos de dados do SQL Server/tabelas externas

O U-SQL fornece fonte de dados e tabelas externas, bem como consultas diretas no Banco de Dados SQL do Azure. Embora o Spark não ofereça as mesmas abstrações de objeto, ele fornece o conector Spark para o Banco de Dados SQL do Azure que pode ser usado para consultar bancos de dados SQL.

Parâmetros e variáveis U-SQL

Parâmetros e variáveis de usuário têm conceitos equivalentes no Spark e seus idiomas de hospedagem.

Por exemplo, no Scala, você pode definir uma variável com a var palavra-chave:

var x = 2 * 3;
println(x)

As variáveis de sistema do U-SQL (variáveis começando com @@) podem ser divididas em duas categorias:

  • Variáveis de sistema configuráveis que podem ser definidas como valores específicos para afetar o comportamento dos scripts
  • Variáveis do sistema de informação que consultam informações sobre o sistema e o nível do trabalho

A maioria das variáveis de sistema configuráveis não tem equivalente direto no Spark. Algumas das variáveis do sistema de informação podem ser modeladas passando as informações como argumentos durante a execução do trabalho, outras podem ter uma função equivalente na linguagem de hospedagem do Spark.

Dicas U-SQL

O U-SQL oferece várias maneiras sintáticas de fornecer dicas para o otimizador de consulta e o mecanismo de execução:

  • Definindo uma variável de sistema U-SQL
  • Uma OPTION cláusula associada à expressão do conjunto de linhas para fornecer uma dica de dados ou plano
  • Uma dica de junção na sintaxe da expressão de junção (por exemplo, BROADCASTLEFT)

O otimizador de consulta baseado em custos do Spark tem seus próprios recursos para fornecer dicas e ajustar o desempenho da consulta. Consulte a documentação correspondente.

Próximos passos