Migrando o Time Series Insights (TSI) Gen2 para o Azure Data Explorer
Nota
O serviço Time Series Insights (TSI) deixará de ser suportado após março de 2025. Ponderar, o mais rapidamente possível, a migração dos ambientes ETI existentes para soluções alternativas. Para obter mais informações sobre a substituição e migração, visite nossa documentação.
Descrição geral
Recomendações de migração de alto nível.
Caraterística | Estado Gen2 | Migração recomendada |
---|---|---|
Ingerir JSON do Hub com achatamento e fuga | Ingestão de ETI | ADX - OneClick Ingest / Assistente |
Abrir câmara frigorífica | Conta de armazenamento do cliente | Exportação contínua de dados para a tabela externa especificada pelo cliente no ADLS. |
Conector PBI | Pré-visualização Privada | Use o conector ADX PBI. Reescreva o TSQ no KQL manualmente. |
Apache Spark Connector | Pré-visualização Privada. Consultar dados de telemetria. Dados do modelo de consulta. | Migre dados para o ADX. Use o conector ADX Spark para dados de telemetria + exporte o modelo para JSON e carregue no Spark. Reescreva consultas no KQL. |
Carregamento em Massa | Pré-visualização Privada | Use ADX OneClick Ingest e LightIngest. Opcionalmente, configure o particionamento no ADX. |
Modelo de Série de Tempo | Pode ser exportado como arquivo JSON. Pode ser importado para o ADX para realizar junções no KQL. | |
Explorador da ETI | Alternando quente e frio | Painéis ADX |
Linguagem da consulta | Consultas de séries temporais (TSQ) | Reescreva consultas no KQL. Use SDKs Kusto em vez de TSI. |
Migrando telemetria
Use PT=Time
a pasta na conta de armazenamento para recuperar a cópia de toda a telemetria no ambiente. Para obter mais informações, consulte Armazenamento de dados.
Etapa de migração 1 – Obter estatísticas sobre dados de telemetria
Dados
- Visão geral do Env
- ID do ambiente de registro da primeira parte do FQDN de acesso a dados (por exemplo, d390b0b0-1445-4c0c-8365-68d6382c1c2a de .env.crystal-dev.windows-int.net)
- Visão geral do Env -> Configuração de armazenamento -> Conta de armazenamento
- Use o Gerenciador de Armazenamento para obter estatísticas de pastas
- Tamanho do registro e o número de blobs da
PT=Time
pasta. Para clientes em visualização privada da Importação em Massa, registre tambémPT=Import
o tamanho e o número de blobs.
- Tamanho do registro e o número de blobs da
Etapa de migração 2 – Migrar telemetria para ADX
Criar cluster ADX
Defina o tamanho do cluster com base no tamanho dos dados usando o ADX Cost Estimator.
- A partir das métricas dos Hubs de Eventos (ou Hub IoT), recupere a taxa de quantidade de dados ingeridos por dia. A partir da Conta de armazenamento conectada ao ambiente da ETI, recupere a quantidade de dados existente no contêiner de blob usado pela ETI. Essas informações serão usadas para calcular o tamanho ideal de um cluster ADX para seu ambiente.
- Abra o Estimador de Custos do Azure Data Explorer e preencha os campos existentes com as informações encontradas. Defina "Tipo de carga de trabalho" como "Armazenamento otimizado" e "Hot Data" com a quantidade total de dados consultados ativamente.
- Depois de fornecer todas as informações, o Estimador de Custos do Azure Data Explorer sugerirá um tamanho de VM e o número de instâncias para seu cluster. Analise se o tamanho dos dados consultados ativamente caberá no Hot Cache. Multiplique o número de instâncias sugerido pelo tamanho do cache do tamanho da VM, por exemplo:
- Sugestão do estimador de custos: 9x DS14 + 4 TB (cache)
- Total de Hot Cache sugerido: 36 TB = [9x (instâncias) x 4 TB (de Hot Cache por nó)]
- Mais fatores a considerar:
- Crescimento do ambiente: ao planejar o tamanho do cluster ADX, considere o crescimento dos dados ao longo do tempo.
- Hidratação e particionamento: ao definir o número de instâncias no ADX Cluster, considere nós extras (de 2 a 3x) para acelerar a hidratação e o particionamento.
- Para obter mais informações sobre seleção de computação, consulte Selecionar a SKU de computação correta para seu cluster do Azure Data Explorer.
Para monitorar melhor o cluster e a ingestão de dados, habilite as Configurações de diagnóstico e envie os dados para um espaço de trabalho do Log Analytics.
Na folha Azure Data Explorer, vá para "Monitoramento | Configurações de diagnóstico" e clique em "Adicionar configuração de diagnóstico"
Preencha o seguinte
- Nome da configuração de diagnóstico: Nome de exibição para esta configuração
- Logs: No mínimo, selecione SucceededIngestion, FailedIngestion, IngestionBatching
- Selecione o espaço de trabalho do Log Analytics para o qual enviar os dados (se você não tiver um, precisará provisionar um antes desta etapa)
Particionamento de dados.
- Para a maioria dos conjuntos de dados, o particionamento ADX padrão é suficiente.
- O particionamento de dados é benéfico em um conjunto muito específico de cenários e não deve ser aplicado de outra forma:
- Melhorar a latência da consulta em conjuntos de big data em que a maioria das consultas filtra em uma coluna de cadeia de caracteres de cardinalidade alta, por exemplo, um ID de série temporal.
- Ao ingerir dados fora de ordem, por exemplo, quando eventos do passado podem ser ingeridos dias ou semanas após a sua geração na origem.
- Para obter mais informações, consulte Política de particionamento de dados ADX.
Prepare-se para a ingestão de dados
Aceder a https://dataexplorer.azure.com.
Vá para a guia Dados e selecione 'Ingerir do contêiner de blob'
Selecione Cluster, Database e crie uma nova tabela com o nome escolhido para os dados da ETI
Selecione Seguinte: Origem
Na guia Origem, selecione:
- Dados históricos
- "Selecionar recipiente"
- Escolha a conta de Subscrição e Armazenamento para os seus dados da ETI
- Escolha o contêiner correlacionado ao seu ambiente de ETI
Selecione em Configurações avançadas
- Padrão de tempo de criação: '/'yyyyMMddHHmmssfff'_'
- Padrão do nome do blob: *.parquet
- Selecione "Não espere a ingestão terminar"
Em Filtros de Ficheiros, adicione o caminho da pasta
V=1/PT=Time
Selecione Próximo: Esquema
Nota
A ETI aplica algum nivelamento e fuga ao persistir colunas em arquivos Parquet. Veja estes links para obter mais detalhes: regras de achatamento e fuga, atualizações de regras de ingestão.
Se o esquema for desconhecido ou estiver variando
Se o esquema for conhecido ou corrigido
- Confirme se os dados estão corretos. Corrija quaisquer tipos, se necessário.
- Selecione Próximo: Resumo
Copie o comando LightIngest e armazene-o em algum lugar para que você possa usá-lo na próxima etapa.
Ingestion de Dados
Antes de ingerir dados, você precisa instalar a ferramenta LightIngest. O comando gerado a partir da ferramenta One-Click inclui um token SAS. É melhor gerar um novo para que você tenha controle sobre o tempo de expiração. No portal, navegue até o contêiner de Blob para o ambiente TSI e selecione 'Token de acesso compartilhado'
Nota
Também é recomendado aumentar a escala do cluster antes de iniciar uma grande ingestão. Por exemplo, D14 ou D32 com 8+ instâncias.
Defina o seguinte
- Permissões: Ler e Listar
- Prazo de validade: defina para um período em que você se sinta confortável que a migração de dados será concluída
Selecione em 'Gerar token e URL SAS' e copie o 'URL SAS de Blob'
Vá para o comando LightIngest que você copiou anteriormente. Substitua o parâmetro -source no comando por este 'URL de Blob SAS'
Opção 1: Ingerir todos os dados. Para ambientes menores, você pode ingerir todos os dados com um único comando.
- Abra um prompt de comando e mude para o diretório para o qual a ferramenta LightIngest foi extraída. Uma vez lá, cole o comando LightIngest e execute-o.
Opção 2: Ingerir dados por ano ou mês. Para ambientes maiores ou para testar em um conjunto de dados menor, você pode filtrar ainda mais o comando Lightingest.
Por ano: altere o parâmetro -prefix
- Antes:
-prefix:"V=1/PT=Time"
- Depois:
-prefix:"V=1/PT=Time/Y=<Year>"
- Exemplo:
-prefix:"V=1/PT=Time/Y=2021"
- Antes:
Por mês: altere o parâmetro -prefix
- Antes:
-prefix:"V=1/PT=Time"
- Depois:
-prefix:"V=1/PT=Time/Y=<Year>/M=<month #>"
- Exemplo:
-prefix:"V=1/PT=Time/Y=2021/M=03"
- Antes:
Depois de modificar o comando, execute-o como acima. Uma vez que a ingestão está completa (usando a opção de monitoramento abaixo) modifique o comando para o próximo ano e mês que você deseja ingerir.
Monitorização da ingestão
O comando LightIngest incluiu o sinalizador -dontWait para que o comando em si não espere a ingestão ser concluída. A melhor maneira de monitorar o progresso enquanto ele está acontecendo é utilizar a guia "Insights" dentro do portal. Abra a seção do cluster do Azure Data Explorer no portal e vá para 'Monitoramento | Perceções»
Você pode usar a seção 'Ingestão (visualização)' com as configurações abaixo para monitorar a ingestão enquanto ela está acontecendo
- Intervalo de tempo: Últimos 30 minutos
- Olhe para Bem Sucedido e por Tabela
- Se você tiver alguma falha, olhe para Falha e por Tabela
Você saberá que a ingestão está completa quando ver as métricas irem para 0 para sua tabela. Se quiser ver mais detalhes, você pode usar o Log Analytics. Na seção cluster do Azure Data Explorer, selecione na guia 'Log':
Consultas Úteis
Compreender o esquema se o esquema dinâmico for usado
| project p=treepath(fullrecord)
| mv-expand p
| summarize by tostring(p)
Acessando valores na matriz
| where id_string == "a"
| summarize avg(todouble(fullrecord.['nestedArray_v_double'])) by bin(timestamp, 1s)
| render timechart
Migrando o Modelo de Série Temporal (TSM) para o Azure Data Explorer
O modelo pode ser baixado em formato JSON do Ambiente TSI usando o TSI Explorer UX ou TSM Batch API. Em seguida, o modelo pode ser importado para outro sistema, como o Azure Data Explorer.
Faça o download do TSM da TSI UX.
Exclua as três primeiras linhas usando o VSCode ou outro editor.
Usando o VSCode ou outro editor, pesquise e substitua como regex
\},\n \{
por}{
Ingerir como JSON no ADX como uma tabela separada usando a funcionalidade Upload from file.
Traduzir Consultas de Série Temporal (TSQ) para KQL
GetEvents
{
"getEvents": {
"timeSeriesId": [
"assest1",
"siteId1",
"dataId1"
],
"searchSpan": {
"from": "2021-11-01T00:00:0.0000000Z",
"to": "2021-11-05T00:00:00.000000Z"
},
"inlineVariables": {},
}
}
events
| where timestamp >= datetime(2021-11-01T00:00:0.0000000Z) and timestamp < datetime(2021-11-05T00:00:00.000000Z)
| where assetId_string == "assest1" and siteId_string == "siteId1" and dataid_string == "dataId1"
| take 10000
GetEvents com filtro
{
"getEvents": {
"timeSeriesId": [
"deviceId1",
"siteId1",
"dataId1"
],
"searchSpan": {
"from": "2021-11-01T00:00:0.0000000Z",
"to": "2021-11-05T00:00:00.000000Z"
},
"filter": {
"tsx": "$event.sensors.sensor.String = 'status' AND $event.sensors.unit.String = 'ONLINE"
}
}
}
events
| where timestamp >= datetime(2021-11-01T00:00:0.0000000Z) and timestamp < datetime(2021-11-05T00:00:00.000000Z)
| where deviceId_string== "deviceId1" and siteId_string == "siteId1" and dataId_string == "dataId1"
| where ['sensors.sensor_string'] == "status" and ['sensors.unit_string'] == "ONLINE"
| take 10000
GetEvents com variável projetada
{
"getEvents": {
"timeSeriesId": [
"deviceId1",
"siteId1",
"dataId1"
],
"searchSpan": {
"from": "2021-11-01T00:00:0.0000000Z",
"to": "2021-11-05T00:00:00.000000Z"
},
"inlineVariables": {},
"projectedVariables": [],
"projectedProperties": [
{
"name": "sensors.value",
"type": "String"
},
{
"name": "sensors.value",
"type": "bool"
},
{
"name": "sensors.value",
"type": "Double"
}
]
}
}
events
| where timestamp >= datetime(2021-11-01T00:00:0.0000000Z) and timestamp < datetime(2021-11-05T00:00:00.000000Z)
| where deviceId_string== "deviceId1" and siteId_string == "siteId1" and dataId_string == "dataId1"
| take 10000
| project timestamp, sensorStringValue= ['sensors.value_string'], sensorBoolValue= ['sensors.value_bool'], sensorDoublelValue= ['sensors.value_double']
Série Agregada
{
"aggregateSeries": {
"timeSeriesId": [
"deviceId1"
],
"searchSpan": {
"from": "2021-11-01T00:00:00.0000000Z",
"to": "2021-11-05T00:00:00.0000000Z"
},
"interval": "PT1M",
"inlineVariables": {
"sensor": {
"kind": "numeric",
"value": {
"tsx": "coalesce($event.sensors.value.Double, todouble($event.sensors.value.Long))"
},
"aggregation": {
"tsx": "avg($value)"
}
}
},
"projectedVariables": [
"sensor"
]
}
events
| where timestamp >= datetime(2021-11-01T00:00:00.0000000Z) and timestamp < datetime(2021-11-05T00:00:00.0000000Z)
| where deviceId_string == "deviceId1"
| summarize avgSensorValue= avg(coalesce(['sensors.value_double'], todouble(['sensors.value_long']))) by bin(IntervalTs = timestamp, 1m)
| project IntervalTs, avgSensorValue
AggregateSeries com filtro
{
"aggregateSeries": {
"timeSeriesId": [
"deviceId1"
],
"searchSpan": {
"from": "2021-11-01T00:00:00.0000000Z",
"to": "2021-11-05T00:00:00.0000000Z"
},
"filter": {
"tsx": "$event.sensors.sensor.String = 'heater' AND $event.sensors.location.String = 'floor1room12'"
},
"interval": "PT1M",
"inlineVariables": {
"sensor": {
"kind": "numeric",
"value": {
"tsx": "coalesce($event.sensors.value.Double, todouble($event.sensors.value.Long))"
},
"aggregation": {
"tsx": "avg($value)"
}
}
},
"projectedVariables": [
"sensor"
]
}
}
events
| where timestamp >= datetime(2021-11-01T00:00:00.0000000Z) and timestamp < datetime(2021-11-05T00:00:00.0000000Z)
| where deviceId_string == "deviceId1"
| where ['sensors.sensor_string'] == "heater" and ['sensors.location_string'] == "floor1room12"
| summarize avgSensorValue= avg(coalesce(['sensors.value_double'], todouble(['sensors.value_long']))) by bin(IntervalTs = timestamp, 1m)
| project IntervalTs, avgSensorValue
Migração do TSI Power BI Connector para o ADX Power BI Connector
As etapas manuais envolvidas nessa migração são:
- Converter consulta do Power BI em TSQ
- Converter TSQ para KQL Consulta do Power BI para TSQ: A consulta do Power BI copiada do TSI UX Explorer tem a aparência mostrada abaixo
Para dados brutos (API GetEvents)
{"storeType":"ColdStore","isSearchSpanRelative":false,"clientDataType":"RDX_20200713_Q","environmentFqdn":"6988946f-2b5c-4f84-9921-530501fbab45.env.timeseries.azure.com", "queries":[{"getEvents":{"searchSpan":{"from":"2019-10-31T23:59:39.590Z","to":"2019-11-01T05:22:18.926Z"},"timeSeriesId":["Arctic Ocean",null],"take":250000}}]}
- Para convertê-lo em TSQ, crie um JSON a partir da carga útil acima. A documentação da API GetEvents também tem exemplos para entendê-la melhor. Consulta - Executar - API REST (Azure Time Series Insights) | Documentos Microsoft
- O TSQ convertido parece como mostrado abaixo. É a carga JSON dentro de "consultas"
{
"getEvents": {
"timeSeriesId": [
"Arctic Ocean",
"null"
],
"searchSpan": {
"from": "2019-10-31T23:59:39.590Z",
"to": "2019-11-01T05:22:18.926Z"
},
"take": 250000
}
}
Para dados Aggradate (API da série agregada)
- Para uma única variável embutida, a consulta do PowerBI do TSI UX Explorer tem a aparência mostrada abaixo:
{"storeType":"ColdStore","isSearchSpanRelative":false,"clientDataType":"RDX_20200713_Q","environmentFqdn":"6988946f-2b5c-4f84-9921-530501fbab45.env.timeseries.azure.com", "queries":[{"aggregateSeries":{"searchSpan":{"from":"2019-10-31T23:59:39.590Z","to":"2019-11-01T05:22:18.926Z"},"timeSeriesId":["Arctic Ocean",null],"interval":"PT1M", "inlineVariables":{"EventCount":{"kind":"aggregate","aggregation":{"tsx":"count()"}}},"projectedVariables":["EventCount"]}}]}
- Para convertê-lo em TSQ, crie um JSON a partir da carga útil acima. A documentação da API AggregateSeries também tem exemplos para entendê-la melhor. Consulta - Executar - API REST (Azure Time Series Insights) | Documentos Microsoft
- O TSQ convertido parece como mostrado abaixo. É a carga JSON dentro de "consultas"
{
"aggregateSeries": {
"timeSeriesId": [
"Arctic Ocean",
"null"
],
"searchSpan": {
"from": "2019-10-31T23:59:39.590Z",
"to": "2019-11-01T05:22:18.926Z"
},
"interval": "PT1M",
"inlineVariables": {
"EventCount": {
"kind": "aggregate",
"aggregation": {
"tsx": "count()"
}
}
},
"projectedVariables": [
"EventCount",
]
}
}
- Para mais de uma variável embutida, acrescente o json em "inlineVariables", conforme mostrado no exemplo abaixo. A consulta do Power BI para mais de uma variável embutida tem a seguinte aparência:
{"storeType":"ColdStore","isSearchSpanRelative":false,"clientDataType":"RDX_20200713_Q","environmentFqdn":"6988946f-2b5c-4f84-9921-530501fbab45.env.timeseries.azure.com","queries":[{"aggregateSeries":{"searchSpan":{"from":"2019-10-31T23:59:39.590Z","to":"2019-11-01T05:22:18.926Z"},"timeSeriesId":["Arctic Ocean",null],"interval":"PT1M", "inlineVariables":{"EventCount":{"kind":"aggregate","aggregation":{"tsx":"count()"}}},"projectedVariables":["EventCount"]}}, {"aggregateSeries":{"searchSpan":{"from":"2019-10-31T23:59:39.590Z","to":"2019-11-01T05:22:18.926Z"},"timeSeriesId":["Arctic Ocean",null],"interval":"PT1M", "inlineVariables":{"Magnitude":{"kind":"numeric","value":{"tsx":"$event['mag'].Double"},"aggregation":{"tsx":"max($value)"}}},"projectedVariables":["Magnitude"]}}]}
{
"aggregateSeries": {
"timeSeriesId": [
"Arctic Ocean",
"null"
],
"searchSpan": {
"from": "2019-10-31T23:59:39.590Z",
"to": "2019-11-01T05:22:18.926Z"
},
"interval": "PT1M",
"inlineVariables": {
"EventCount": {
"kind": "aggregate",
"aggregation": {
"tsx": "count()"
}
},
"Magnitude": {
"kind": "numeric",
"value": {
"tsx": "$event['mag'].Double"
},
"aggregation": {
"tsx": "max($value)"
}
}
},
"projectedVariables": [
"EventCount",
"Magnitude",
]
}
}
- Se você quiser consultar os dados mais recentes("isSearchSpanRelative": true), calcule manualmente o searchSpan como mencionado abaixo
- Encontre a diferença entre "de" e "para" da carga útil do Power BI. Vamos chamar essa diferença de "D", onde "D" = "de" - "para"
- Pegue o carimbo de data/hora atual ("T") e subtraia a diferença obtida na primeira etapa. Será novo "from"(F) de searchSpan onde "F" = "T" - "D"
- Agora, o novo "de" é "F" obtido na etapa 2 e o novo "para" é "T" (carimbo de data/hora atual)