Partilhar via


Resolver problemas de distorção de dados no Azure Data Lake Analytics com o Azure Data Lake Tools para Visual Studio

Importante

O Azure Data Lake Analytics descontinuado a 29 de fevereiro de 2024. Saiba mais com este anúncio.

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

O que é a distorção de dados?

Resumidamente, a distorção de dados é um valor sobre-representado. Imagine que atribuiu 50 examinadores fiscais a declarações fiscais de auditoria, um examinador para cada estado dos EUA. O examinador de Wyoming, porque a população lá é pequena, tem pouco a fazer. Na Califórnia, no entanto, o examinador é mantido ocupado por causa da grande população do estado.

Um gráfico de colunas de exemplo que mostra a maioria dos dados a serem agrupados em duas colunas, em vez de serem distribuídos uniformemente por categorias.

No nosso cenário, os dados são distribuídos de forma desigual por todos os examinadores fiscais, o que significa que alguns examinadores têm de trabalhar mais do que outros. No seu próprio trabalho, tem frequentemente situações como o exemplo do fiscal-examiner aqui. Em termos mais técnicos, um vértice obtém muito mais dados do que os seus pares, uma situação que faz com que o vértice funcione mais do que os outros e que, eventualmente, abranda um trabalho inteiro. O que é pior, a tarefa pode falhar, porque os vértices podem ter, por exemplo, uma limitação de tempo de execução de 5 horas e uma limitação de memória de 6 GB.

Resolver problemas de distorção de dados

O Azure Data Lake Tools para Visual Studio e Visual Studio Code pode ajudar a detetar se a sua tarefa tem um problema de distorção de dados.

Se existir um problema, pode resolvê-lo ao experimentar as soluções nesta secção.

Solução 1: Melhorar a criação de partições de tabelas

Opção 1: filtrar o valor da chave distorcida com antecedência

Se não afetar a sua lógica de negócio, pode filtrar os valores de maior frequência com antecedência. Por exemplo, se existirem muitos 000-000-000 no GUID da coluna, poderá não querer agregar esse valor. Antes de agregar, pode escrever "WHERE GUID != "000-000-000"" para filtrar o valor de alta frequência.

Opção 2: escolher uma partição ou chave de distribuição diferente

No exemplo anterior, se quiser verificar apenas a carga de trabalho de auditoria fiscal em todo o país/região, pode melhorar a distribuição de dados ao selecionar o número de ID como chave. Escolher uma partição ou chave de distribuição diferente pode, por vezes, distribuir os dados de forma mais uniforme, mas tem de se certificar de que esta escolha não afeta a sua lógica de negócio. Por exemplo, para calcular a soma do imposto para cada estado, pode designar Estado como a chave de partição. Se continuar a ter este problema, experimente utilizar a Opção 3.

Opção 3: Adicionar mais chaves de partição ou distribuição

Em vez de utilizar apenas o Estado como uma chave de partição, pode utilizar mais do que uma chave para a criação de partições. Por exemplo, considere adicionar Código POSTAL como outra chave de partição para reduzir os tamanhos da partição de dados e distribuir os dados de forma mais uniforme.

Opção 4: Utilizar a distribuição round robin

Se não conseguir encontrar uma chave adequada para partição e distribuição, pode tentar utilizar a distribuição round robin. A distribuição round robin trata todas as linhas de forma igual e aleatoriamente coloca-as em registos correspondentes. Os dados são distribuídos uniformemente, mas perdem as informações de localidade, uma desvantagem que também pode reduzir o desempenho da tarefa em algumas operações. Além disso, se estiver a fazer agregação para a chave distorcida, o problema de distorção de dados irá persistir. Para saber mais sobre a distribuição round robin, veja a secção Distribuições de Tabelas U-SQL em CREATE TABLE (U-SQL): Criar uma Tabela com Esquema.

Solução 2: Melhorar o plano de consulta

Opção 1: utilizar a instrução CREATE STATISTICS

O U-SQL fornece a instrução CREATE STATISTICS em tabelas. Esta instrução fornece mais informações ao otimizador de consultas sobre as características de dados (por exemplo, distribuição de valores) que estão armazenadas numa tabela. Para a maioria das consultas, o otimizador de consultas já gera as estatísticas necessárias para um plano de consulta de alta qualidade. Ocasionalmente, poderá ter de melhorar o desempenho das consultas ao criar mais estatísticas com CREATE STATISTICS ou ao modificar a estrutura da consulta. Para obter mais informações, veja a página CREATE STATISTICS (U-SQL).

Exemplo de código:

CREATE STATISTICS IF NOT EXISTS stats_SampleTable_date ON SampleDB.dbo.SampleTable(date) WITH FULLSCAN;

Nota

As informações de estatística não são atualizadas automaticamente. Se atualizar os dados numa tabela sem recriar as estatísticas, o desempenho da consulta poderá diminuir.

Opção 2: Utilizar o SKEWFACTOR

Se quiser somar o imposto para cada estado, tem de utilizar o estado GROUP BY, uma abordagem que não evite o problema de distorção de dados. No entanto, pode fornecer uma sugestão de dados na consulta para identificar a distorção de dados nas chaves para que o otimizador possa preparar um plano de execução automaticamente.

Normalmente, pode definir o parâmetro como 0,5 e 1, com 0,5 significando pouco distorção e um que significa distorção pesada. Uma vez que a sugestão afeta a otimização do plano de execução para a instrução atual e todas as instruções a jusante, certifique-se de que adiciona a sugestão antes da potencial agregação em termos de chave distorcida.

SKEWFACTOR (columns) = x

Fornece uma sugestão de que as colunas especificadas têm um fator de distorção x de 0 (sem distorção) até 1 (distorção pesada).

Exemplo de código:

//Add a SKEWFACTOR hint.
@Impressions =
    SELECT * FROM
    searchDM.SML.PageView(@start, @end) AS PageView
    OPTION(SKEWFACTOR(Query)=0.5)
    ;
//Query 1 for key: Query, ClientId
@Sessions =
    SELECT
        ClientId,
        Query,
        SUM(PageClicks) AS Clicks
    FROM
        @Impressions
    GROUP BY
        Query, ClientId
    ;
//Query 2 for Key: Query
@Display =
    SELECT * FROM @Sessions
        INNER JOIN @Campaigns
            ON @Sessions.Query == @Campaigns.Query
    ;

Opção 3: Utilizar ROWCOUNT

Além do SKEWFACTOR, para casos específicos de associação de chave distorcida, se souber que o outro conjunto de linhas associadas é pequeno, pode indicar ao otimizador ao adicionar uma sugestão ROWCOUNT na instrução U-SQL antes de JOIN. Desta forma, o otimizador pode escolher uma estratégia de associação de difusão para ajudar a melhorar o desempenho. Tenha em atenção que a ROWCOUNT não resolve o problema de distorção de dados, mas pode oferecer ajuda adicional.

OPTION(ROWCOUNT = n)

Identifique um pequeno conjunto de linhas antes de JOIN, fornecendo uma contagem estimada de linhas de número inteiro.

Exemplo de código:

//Unstructured (24-hour daily log impressions)
@Huge   = EXTRACT ClientId int, ...
            FROM @"wasb://ads@wcentralus/2015/10/30/{*}.nif"
            ;
//Small subset (that is, ForgetMe opt out)
@Small  = SELECT * FROM @Huge
            WHERE Bing.ForgetMe(x,y,z)
            OPTION(ROWCOUNT=500)
            ;
//Result (not enough information to determine simple broadcast JOIN)
@Remove = SELECT * FROM Bing.Sessions
            INNER JOIN @Small ON Sessions.Client == @Small.Client
            ;

Solução 3: Melhorar o redutor e a combinação definidos pelo utilizador

Por vezes, pode escrever um operador definido pelo utilizador para lidar com lógicas de processo complicadas e uma redução e combinação bem escritas podem mitigar um problema de distorção de dados em alguns casos.

Opção 1: utilizar um redutor recursivo, se possível

Por predefinição, um redutor definido pelo utilizador é executado no modo não recursivo, o que significa que o trabalho de redução de uma chave é distribuído num único vértice. No entanto, se os seus dados forem distorcidos, os conjuntos de dados enormes poderão ser processados num único vértice e executados durante muito tempo.

Para melhorar o desempenho, pode adicionar um atributo no seu código para definir o redudor a ser executado no modo recursivo. Em seguida, os conjuntos de dados enormes podem ser distribuídos por múltiplos vértices e executados em paralelo, o que acelera a tarefa.

Para alterar um redutor não recursivo para recursivo, tem de se certificar de que o algoritmo é associativo. Por exemplo, a soma é associativa e a mediana não. Também tem de se certificar de que a entrada e a saída do redutor mantêm o mesmo esquema.

Atributo do redutor recursivo:

[SqlUserDefinedReducer(IsRecursive = true)]

Exemplo de código:

[SqlUserDefinedReducer(IsRecursive = true)]
public class TopNReducer : IReducer
{
    public override IEnumerable<IRow>
        Reduce(IRowset input, IUpdatableRow output)
    {
        //Your reducer code goes here.
    }
}

Opção 2: utilizar o modo de combinação ao nível da linha, se possível

À semelhança da sugestão ROWCOUNT para casos específicos de associação de chave distorcida, o modo de combinação tenta distribuir conjuntos de valores de chave distorcida enormes para múltiplos vértices para que o trabalho possa ser executado em simultâneo. O modo de combinação não consegue resolver problemas de distorção de dados, mas pode oferecer ajuda adicional para grandes conjuntos de valores de chave distorcida.

Por predefinição, o modo de combinação é Completo, o que significa que o conjunto de linhas esquerda e a linha direita não podem ser separados. Definir o modo como Esquerda/Direita/Interior ativa a associação ao nível da linha. O sistema separa os conjuntos de linhas correspondentes e distribui-os em múltiplos vértices que são executados em paralelo. No entanto, antes de configurar o modo de combinação, tenha cuidado para garantir que os conjuntos de linhas correspondentes podem ser separados.

O exemplo que se segue mostra um conjunto de linhas esquerda separados. Cada linha de saída depende de uma única linha de entrada da esquerda e, potencialmente, depende de todas as linhas da direita com o mesmo valor de chave. Se definir o modo de combinação como à esquerda, o sistema separa o enorme conjunto de linhas esquerdas em pequenos e atribui-os a múltiplos vértices.

Duas colunas de linhas que representam conjuntos de dados à esquerda e à direita, que mostram algumas linhas do conjunto de dados à direita a serem movidas para o primeiro grupo do conjunto de dados esquerdo.

Nota

Se definir o modo de combinação errado, a combinação é menos eficiente e os resultados poderão estar errados.

Atributos do modo de combinação:

  • SqlUserDefinedCombiner(Mode=CombinerMode.Full): cada linha de saída depende potencialmente de todas as linhas de entrada da esquerda e da direita com o mesmo valor de chave.

  • SqlUserDefinedCombiner(Mode=CombinerMode.Left): cada linha de saída depende de uma única linha de entrada da esquerda (e, potencialmente, de todas as linhas da direita com o mesmo valor de chave).

  • qlUserDefinedCombiner(Mode=CombinerMode.Right): cada linha de saída depende de uma única linha de entrada da direita (e potencialmente todas as linhas da esquerda com o mesmo valor de chave).

  • SqlUserDefinedCombiner(Mode=CombinerMode.Inner): cada linha de saída depende de uma única linha de entrada da esquerda e da direita com o mesmo valor.

Exemplo de código:

[SqlUserDefinedCombiner(Mode = CombinerMode.Right)]
public class WatsonDedupCombiner : ICombiner
{
    public override IEnumerable<IRow>
        Combine(IRowset left, IRowset right, IUpdatableRow output)
    {
    //Your combiner code goes here.
    }
}