Tirar partido da paralelização de consultas no Azure Stream Analytics

Este artigo mostra-lhe como tirar partido da paralelização no Azure Stream Analytics. Saiba como dimensionar tarefas do Stream Analytics ao configurar partições de entrada e ajustar a definição de consulta de análise. Como pré-requisito, poderá querer estar familiarizado com a noção de Unidade de Transmissão em Fluxo descrita em Compreender e ajustar As Unidades de Transmissão em Fluxo.

Quais são as partes de uma tarefa do Stream Analytics?

Uma definição de tarefa do Stream Analytics inclui, pelo menos, uma entrada de transmissão em fluxo, uma consulta e uma saída. As entradas são a partir de onde a tarefa lê o fluxo de dados. A consulta é utilizada para transformar o fluxo de entrada de dados e a saída é para onde a tarefa envia os resultados da tarefa.

Partições em entradas e saídas

A criação de partições permite-lhe dividir dados em subconjuntos com base numa chave de partição. Se a sua entrada (por exemplo, Hubs de Eventos) estiver particionada por uma chave, é altamente recomendado especificar esta chave de partição ao adicionar entradas à tarefa do Stream Analytics. O dimensionamento de uma tarefa do Stream Analytics tira partido das partições na entrada e saída. Uma tarefa do Stream Analytics pode consumir e escrever partições diferentes em paralelo, o que aumenta o débito.

Entradas

Todas as entradas de transmissão em fluxo do Azure Stream Analytics podem tirar partido da criação de partições: Hubs de Eventos, Hub IoT, Armazenamento de blobs.

Nota

Para o nível de compatibilidade 1.2 e superior, a chave de partição deve ser definida como uma propriedade de entrada, sem necessidade da palavra-chave PARTIÇÃO POR na consulta. Para o nível de compatibilidade 1.1 e inferior, a chave de partição tem de ser definida com a palavra-chave PARTITION BY na consulta.

Saídas

Quando trabalha com o Stream Analytics, pode tirar partido da criação de partições nas saídas:

  • Azure Data Lake Storage
  • Funções do Azure
  • Tabela do Azure
  • Armazenamento de blobs (pode definir explicitamente a chave de partição)
  • Azure Cosmos DB (precisa de definir explicitamente a chave de partição)
  • Hubs de Eventos (precisa de definir explicitamente a chave de partição)
  • Hub IoT (tem de definir explicitamente a chave de partição)
  • Service Bus
  • SQL e Azure Synapse Analytics com criação de partições opcionais: veja mais informações na página Saída para SQL do Azure Base de Dados.

O Power BI não suporta a criação de partições. No entanto, ainda pode particionar a entrada conforme descrito nesta secção

Para obter mais informações sobre partições, consulte os seguintes artigos:

Consulta

Para que uma tarefa seja paralela, as chaves de partição têm de estar alinhadas entre todas as entradas, todos os passos de lógica de consulta e todas as saídas. A criação de partições lógicas de consulta é determinada pelas chaves utilizadas para associações e agregações (GROUP BY). Este último requisito pode ser ignorado se a lógica de consulta não estiver com chave (projeção, filtros, associações referenciais...).

  • Se uma entrada e uma saída forem particionadas por WarehouseId e os grupos de consulta por ProductId sem WarehouseId, a tarefa não será paralela.
  • Se duas entradas a associar forem particionadas por chaves de partição diferentes (WarehouseId e ProductId), a tarefa não é paralela.
  • Se dois ou mais fluxos de dados independentes estiverem contidos numa única tarefa, cada um com a sua própria chave de partição, a tarefa não é paralela.

Só quando todas as entradas, saídas e passos de consulta estiverem a utilizar a mesma chave é que a tarefa será paralela.

Tarefas embaraçosamente paralelas

Uma tarefa embaraçosamente paralela é o cenário mais dimensionável no Azure Stream Analytics. Liga uma partição da entrada a uma instância da consulta a uma partição da saída. Este paralelismo tem os seguintes requisitos:

  1. Se a lógica de consulta depender da mesma chave que está a ser processada pela mesma instância de consulta, tem de se certificar de que os eventos vão para a mesma partição da sua entrada. Para os Hubs de Eventos ou Hub IoT, isto significa que os dados do evento têm de ter o valor PartitionKey definido. Em alternativa, pode utilizar remetentes particionados. Para o armazenamento de blobs, isto significa que os eventos são enviados para a mesma pasta de partição. Um exemplo seria uma instância de consulta que agrega dados por userID em que o hub de eventos de entrada é particionado com userID como chave de partição. No entanto, se a lógica de consulta não exigir que a mesma chave seja processada pela mesma instância de consulta, pode ignorar este requisito. Um exemplo desta lógica seria uma consulta select-project-filter simples.

  2. O próximo passo é fazer com que a consulta seja particionada. Para tarefas com o nível de compatibilidade 1.2 ou superior (recomendado), a coluna personalizada pode ser especificada como Chave de Partição nas definições de entrada e a tarefa será paralellada automaticamente. Os trabalhos com o nível de compatibilidade 1.0 ou 1.1 requerem que utilize PARTITION BY PartitionId em todos os passos da consulta. São permitidos vários passos, mas todos têm de ser particionados pela mesma chave.

  3. A maioria das saídas suportadas no Stream Analytics pode tirar partido da criação de partições. Se utilizar um tipo de saída que não suporte a criação de partições, a sua tarefa não será embaraçosamente paralela. Para a saída dos Hubs de Eventos, certifique-se de que a coluna Chave de partição está definida para a mesma chave de partição utilizada na consulta. Veja a secção de saída para obter mais detalhes.

  4. O número de partições de entrada tem de ser igual ao número de partições de saída. A saída do armazenamento de blobs pode suportar partições e herda o esquema de criação de partições da consulta a montante. Quando uma chave de partição para o armazenamento de Blobs é especificada, os dados são particionados por partição de entrada, pelo que o resultado ainda é totalmente paralelo. Eis exemplos de valores de partição que permitem uma tarefa totalmente paralela:

    • Oito partições de entrada do hub de eventos e oito partições de saída do hub de eventos
    • Oito partições de entrada do hub de eventos e a saída do armazenamento de blobs
    • Oito partições de entrada do hub de eventos e saída do armazenamento de blobs particionadas por um campo personalizado com cardinalidade arbitrária
    • Oito partições de entrada do armazenamento de blobs e a saída do armazenamento de blobs
    • Oito partições de entrada do armazenamento de blobs e oito partições de saída do hub de eventos

As secções seguintes abordam alguns cenários de exemplo que são embaraçosamente paralelos.

Consulta simples

  • Entrada: Hub de eventos com oito partições
  • Saída: o Hub de Eventos com oito partições ("Coluna da chave de partição" tem de ser definida para utilizar "PartitionId")

Consulta:

    --Using compatibility level 1.2 or above
    SELECT TollBoothId
    FROM Input1
    WHERE TollBoothId > 100
    
    --Using compatibility level 1.0 or 1.1
    SELECT TollBoothId
    FROM Input1 PARTITION BY PartitionId
    WHERE TollBoothId > 100

Esta consulta é um filtro simples. Por conseguinte, não precisamos de nos preocupar com a criação de partições da entrada que está a ser enviada para o hub de eventos. Tenha em atenção que os trabalhos com nível de compatibilidade antes da 1.2 têm de incluir a cláusula PARTITION BY PartitionId , pelo que cumpre o requisito n.º 2 anterior. Para o resultado, temos de configurar a saída do hub de eventos na tarefa para que a chave de partição seja definida como PartitionId. Uma última verificação é certificar-se de que o número de partições de entrada é igual ao número de partições de saída.

Consultar com uma chave de agrupamento

  • Entrada: Hub de eventos com oito partições
  • Saída: Armazenamento de blobs

Consulta:

    --Using compatibility level 1.2 or above
    SELECT COUNT(*) AS Count, TollBoothId
    FROM Input1
    GROUP BY TumblingWindow(minute, 3), TollBoothId
    
    --Using compatibility level 1.0 or 1.1
    SELECT COUNT(*) AS Count, TollBoothId
    FROM Input1 Partition By PartitionId
    GROUP BY TumblingWindow(minute, 3), TollBoothId, PartitionId

Esta consulta tem uma chave de agrupamento. Por conseguinte, os eventos agrupados em conjunto têm de ser enviados para a mesma partição dos Hubs de Eventos. Uma vez que neste exemplo agrupamos por TollBoothID, devemos ter a certeza de que TollBoothID é utilizado como a chave de partição quando os eventos são enviados para os Hubs de Eventos. Em seguida, no ASA, podemos utilizar PARTITION BY PartitionId para herdar deste esquema de partição e ativar a paralelização completa. Uma vez que a saída é o armazenamento de blobs, não temos de nos preocupar em configurar um valor de chave de partição, de acordo com o requisito n.º 4.

Exemplo de cenários que não são embaraçosamente paralelos

Na secção anterior, mostrámos alguns cenários embaraçosamente paralelos. Nesta secção, abordamos cenários que não cumprem todos os requisitos para serem embaraçosamente paralelos.

Contagem de partições sem correspondência

  • Entrada: Hub de eventos com oito partições
  • Saída: Hub de eventos com 32 partições

Se a contagem de partições de entrada não corresponder à contagem de partições de saída, a topologia não é embaraçosamente paralela, independentemente da consulta. No entanto, ainda podemos obter algum nível de paralelização.

Consulta com saída não particionada

  • Entrada: Hub de eventos com oito partições
  • Saída: Power BI

A saída do Power BI não suporta atualmente a criação de partições. Portanto, este cenário não é embaraçosamente paralelo.

Consulta de vários passos com diferentes valores PARTITION BY

  • Entrada: Hub de eventos com oito partições
  • Saída: Hub de eventos com oito partições
  • Nível de compatibilidade: 1.0 ou 1.1

Consulta:

    WITH Step1 AS (
    SELECT COUNT(*) AS Count, TollBoothId, PartitionId
    FROM Input1 Partition By PartitionId
    GROUP BY TumblingWindow(minute, 3), TollBoothId, PartitionId
    )

    SELECT SUM(Count) AS Count, TollBoothId
    FROM Step1 Partition By TollBoothId
    GROUP BY TumblingWindow(minute, 3), TollBoothId

Como pode ver, o segundo passo utiliza TollBoothId como a chave de criação de partições. Este passo não é o mesmo que o primeiro passo e, por conseguinte, exige que façamos uma confusão.

Consulta de vários passos com diferentes valores PARTITION BY

  • Entrada: Hub de eventos com oito partições ("Coluna de chave de partição" não definida, predefinição para "PartitionId")
  • Saída: o hub de eventos com oito partições ("Coluna de chave de partição" tem de estar definido para utilizar "TollBoothId")
  • Nível de compatibilidade - 1.2 ou superior

Consulta:

    WITH Step1 AS (
    SELECT COUNT(*) AS Count, TollBoothId
    FROM Input1
    GROUP BY TumblingWindow(minute, 3), TollBoothId
    )

    SELECT SUM(Count) AS Count, TollBoothId
    FROM Step1
    GROUP BY TumblingWindow(minute, 3), TollBoothId

O nível de compatibilidade 1.2 ou superior permite a execução de consultas paralelas por predefinição. Por exemplo, a consulta da secção anterior será particionada desde que a coluna "TollBoothId" esteja definida como Chave de Partição de entrada. A cláusula PARTITION BY PartitionId não é necessária.

Calcular as unidades de transmissão em fluxo máximas de uma tarefa

O número total de unidades de transmissão em fluxo que podem ser utilizadas por uma tarefa do Stream Analytics depende do número de passos na consulta definida para a tarefa e do número de partições para cada passo.

Passos numa consulta

Uma consulta pode ter um ou muitos passos. Cada passo é uma subconsulta definida pela palavra-chave WITH . A consulta que está fora da palavra-chave WITH (apenas uma consulta) também é contabilizada como um passo, como a instrução SELECT na seguinte consulta:

Consulta:

    WITH Step1 AS (
        SELECT COUNT(*) AS Count, TollBoothId
        FROM Input1 Partition By PartitionId
        GROUP BY TumblingWindow(minute, 3), TollBoothId, PartitionId
    )
    SELECT SUM(Count) AS Count, TollBoothId
    FROM Step1
    GROUP BY TumblingWindow(minute,3), TollBoothId

Esta consulta tem dois passos.

Nota

Esta consulta é abordada mais detalhadamente mais à frente no artigo.

Particionar um passo

A criação de partições de um passo requer as seguintes condições:

  • A origem de entrada tem de ser particionada.
  • A instrução SELECT da consulta tem de ser lida a partir de uma origem de entrada particionada.
  • A consulta no passo tem de ter a palavra-chave PARTITION BY .

Quando uma consulta é particionada, os eventos de entrada são processados e agregados em grupos de partições separados e os eventos de saída são gerados para cada um dos grupos. Se quiser uma agregação combinada, tem de criar um segundo passo não particionado para agregar.

Calcular as unidades de transmissão em fluxo máximas para uma tarefa

Todos os passos não particionados em conjunto podem aumentar verticalmente até seis unidades de transmissão em fluxo (SUs) para uma tarefa do Stream Analytics. Além disso, pode adicionar 6 SUs para cada partição num passo particionado. Pode ver alguns exemplos na tabela abaixo.

Consulta SUs Máximas para a tarefa
  • A consulta contém um passo.
  • O passo não está particionado.
6
  • O fluxo de dados de entrada é particionado por 16.
  • A consulta contém um passo.
  • O passo é particionado.
96 (6 * 16 partições)
  • A consulta contém dois passos.
  • Nenhum dos passos é particionado.
6
  • O fluxo de dados de entrada é particionado por 3.
  • A consulta contém dois passos. O passo de entrada é particionado e o segundo passo não é.
  • A instrução SELECT lê a partir da entrada particionada.
24 (18 para passos particionados + 6 para passos não particionados

Exemplos de dimensionamento

A consulta seguinte calcula o número de carros numa janela de três minutos que passa por uma portagem que tem três portagens. Esta consulta pode ser dimensionada até seis SUs.

    SELECT COUNT(*) AS Count, TollBoothId
    FROM Input1
    GROUP BY TumblingWindow(minute, 3), TollBoothId, PartitionId

Para utilizar mais SUs para a consulta, tanto o fluxo de dados de entrada como a consulta têm de ser particionados. Uma vez que a partição do fluxo de dados está definida como 3, a seguinte consulta modificada pode ser aumentada verticalmente para 18 SUs:

    SELECT COUNT(*) AS Count, TollBoothId
    FROM Input1 Partition By PartitionId
    GROUP BY TumblingWindow(minute, 3), TollBoothId, PartitionId

Quando uma consulta é particionada, os eventos de entrada são processados e agregados em grupos de partições separados. Os eventos de saída também são gerados para cada um dos grupos. A criação de partições pode causar alguns resultados inesperados quando o campo GROUP BY não é a chave de partição no fluxo de dados de entrada. Por exemplo, o campo TollBoothId na consulta anterior não é a chave de partição de Input1. O resultado é que os dados de TollBooth #1 podem ser distribuídos em várias partições.

Cada uma das partições Input1 será processada separadamente pelo Stream Analytics. Como resultado, serão criados vários registos da contagem de automóveis para a mesma portagem na mesma janela em cascata. Se não for possível alterar a chave de partição de entrada, este problema pode ser corrigido ao adicionar um passo de não partição para agregar valores entre partições, como no exemplo seguinte:

    WITH Step1 AS (
        SELECT COUNT(*) AS Count, TollBoothId
        FROM Input1 Partition By PartitionId
        GROUP BY TumblingWindow(minute, 3), TollBoothId, PartitionId
    )

    SELECT SUM(Count) AS Count, TollBoothId
    FROM Step1
    GROUP BY TumblingWindow(minute, 3), TollBoothId

Esta consulta pode ser dimensionada para 24 SUs.

Nota

Se estiver a associar dois fluxos, certifique-se de que os fluxos são particionados pela chave de partição da coluna que utiliza para criar as associações. Certifique-se também de que tem o mesmo número de partições em ambos os fluxos.

Alcançar débitos mais elevados em escala

Uma tarefa embaraçosamente paralela é necessária, mas não é suficiente para suportar um débito mais elevado em escala. Todos os sistemas de armazenamento e a respetiva saída do Stream Analytics correspondente têm variações sobre como alcançar o melhor débito de escrita possível. Tal como acontece com qualquer cenário em escala, existem alguns desafios que podem ser resolvidos com as configurações certas. Esta secção aborda as configurações para algumas saídas comuns e fornece amostras para manter as taxas de ingestão de 1 K, 5 K e 10 K por segundo.

As seguintes observações utilizam uma tarefa do Stream Analytics com consulta sem estado (pass-through), um UDF JavaScript básico que escreve em Hubs de Eventos, SQL do Azure ou Azure Cosmos DB.

Hubs de Eventos

Taxa de Ingestão (eventos por segundo) Unidades de Transmissão em Fluxo Recursos de Saída
1 K 1 2 TU
5 K 6 6 TU
10 K 12 10 TU

A solução dos Hubs de Eventos dimensiona linearmente em termos de unidades de transmissão em fluxo (SU) e débito, tornando-a a forma mais eficiente e eficaz de analisar e transmitir dados do Stream Analytics. As tarefas podem ser dimensionadas até 396 SU, o que se traduz aproximadamente no processamento de até 400 MB/s ou 38 biliões de eventos por dia.

SQL do Azure

Taxa de Ingestão (eventos por segundo) Unidades de Transmissão em Fluxo Recursos de Saída
1 K 3 S3
5 K 18 P4
10 K 36 P6

SQL do Azure suporta a escrita em paralelo, denominada Herdar Criação de Partições, mas não está ativada por predefinição. No entanto, ativar a Criação de Partições Herdar, juntamente com uma consulta totalmente paralela, pode não ser suficiente para obter débitos mais elevados. Os débitos de escrita do SQL dependem significativamente da configuração da base de dados e do esquema da tabela. O artigo Desempenho de Saída do SQL tem mais detalhes sobre os parâmetros que podem maximizar o débito de escrita. Conforme indicado no artigo saída do Azure Stream Analytics para SQL do Azure Base de Dados, esta solução não dimensiona linearmente como um pipeline totalmente paralelo para além de 8 partições e pode precisar de ser repartida antes da saída do SQL (ver INTO). Os SKUs Premium são necessários para manter taxas de E/S elevadas, juntamente com a sobrecarga das cópias de segurança de registo que ocorrem a cada poucos minutos.

Azure Cosmos DB

Taxa de Ingestão (eventos por segundo) Unidades de Transmissão em Fluxo Recursos de Saída
1 K 3 RU de 20K
5 K 24 RU de 60 K
10 K 48 RU de 120 K

A saída do Azure Cosmos DB do Stream Analytics foi atualizada para utilizar a integração nativa no nível de compatibilidade 1.2. O nível de compatibilidade 1.2 permite um débito significativamente maior e reduz o consumo de RU em comparação com 1,1, que é o nível de compatibilidade predefinido para novas tarefas. A solução utiliza contentores do Azure Cosmos DB particionados em /deviceId e o resto da solução está configurado de forma idêntica.

Todos os exemplos de Transmissão em Fluxo no Dimensionamento do Azure utilizam os Hubs de Eventos como entrada que é alimentada pela simulação de carga de clientes de teste. Cada evento de entrada é um documento JSON de 1 KB, que traduz facilmente as taxas de ingestão configuradas para taxas de débito (1 MB/s, 5 MB/s e 10 MB/s). Os eventos simulam um dispositivo IoT que envia os seguintes dados JSON (num formulário abreviado) para um máximo de 1000 dispositivos:

{
    "eventId": "b81d241f-5187-40b0-ab2a-940faf9757c0",
    "complexData": {
        "moreData0": 51.3068118685458,
        "moreData22": 45.34076957651598
    },
    "value": 49.02278128887753,
    "deviceId": "contoso://device-id-1554",
    "type": "CO2",
    "createdAt": "2019-05-16T17:16:40.000003Z"
}

Nota

As configurações estão sujeitas a alterações devido aos vários componentes utilizados na solução. Para obter uma estimativa mais precisa, personalize os exemplos para se ajustarem ao seu cenário.

Identificar Estrangulamentos

Utilize o painel Métricas na tarefa do Azure Stream Analytics para identificar estrangulamentos no pipeline. Reveja Eventos de Entrada/Saída para obter o débito e "Atraso de Marca d'água" ou Eventos com Registo de Tarefas Pendentes para ver se a tarefa está a acompanhar a taxa de entrada. Para as métricas dos Hubs de Eventos, procure Pedidos Limitados e ajuste as Unidades de Limiar em conformidade. Para as métricas do Azure Cosmos DB, reveja o intervalo máximo de RU/s consumidas por chave de partição em Débito para garantir que os intervalos de chaves de partição são consumidos uniformemente. Para SQL do Azure BD, monitorize a E/S de Registo e a CPU.

Obter ajuda

Para obter mais assistência, experimente a nossa página de perguntas Microsoft Q&A para o Azure Stream Analytics.

Passos seguintes