Partilhar via


Ingresso na janela de tempo

Aplica-se a: ✅Microsoft FabricAzure Data ExplorerAzure MonitorMicrosoft Sentinel

Muitas vezes, é útil unir dois grandes conjuntos de dados em alguma chave de alta cardinalidade, como um ID de operação ou um ID de sessão, e limitar ainda mais os registros do lado direito ($right) que precisam corresponder a cada registro do lado esquerdo ($left) adicionando uma restrição na "distância de tempo" entre datetime colunas à esquerda e à direita.

A operação acima difere da operação de junção usual, uma vez que para a parte equi-join de correspondência da chave de alta cardinalidade entre os conjuntos de dados esquerdo e direito, o sistema também pode aplicar uma função de distância e usá-la para acelerar consideravelmente a junção.

Observação

Uma função de distância não se comporta como igualdade (isto é, quando dist(x,y) e dist(y,z) são verdadeiras, ela não segue que dist(x,z) também é verdadeira). Isto é por vezes referido como uma "junção diagonal".

Exemplo para identificar sequências de eventos sem janela de tempo

Para identificar sequências de eventos em uma janela de tempo relativamente pequena, este exemplo usa uma tabela T com o seguinte esquema:

  • SessionId: Uma coluna do tipo string com IDs de correlação.
  • EventType: Uma coluna do tipo string que identifica o tipo de evento do registro.
  • Timestamp: Uma coluna do tipo datetime indica quando ocorreu o evento descrito pelo registro.
SessionId Tipo de Evento Carimbo de data/hora
0 Um 2017-10-01T00:00:00Z
0 B 2017-10-01T00:01:00Z
1 B 2017-10-01T00:02:00Z
1 Um 2017-10-01T00:03:00Z
3 Um 2017-10-01T00:04:00Z
3 B 2017-10-01T00:10:00Z

A consulta a seguir cria o conjunto de dados e, em seguida, identifica todas as IDs de sessão em que o tipo de evento A foi seguido por um tipo de evento B dentro de uma janela de tempo 1min.

let T = datatable(SessionId:string, EventType:string, Timestamp:datetime)
[
    '0', 'A', datetime(2017-10-01 00:00:00),
    '0', 'B', datetime(2017-10-01 00:01:00),
    '1', 'B', datetime(2017-10-01 00:02:00),
    '1', 'A', datetime(2017-10-01 00:03:00),
    '3', 'A', datetime(2017-10-01 00:04:00),
    '3', 'B', datetime(2017-10-01 00:10:00),
];
T
| where EventType == 'A'
| project SessionId, Start=Timestamp
| join kind=inner
    (
    T 
    | where EventType == 'B'
    | project SessionId, End=Timestamp
    ) on SessionId
| where (End - Start) between (0min .. 1min)
| project SessionId, Start, End 

Output

SessionId Início Fim
0 2017-10-01 00:00:00.0000000 2017-10-01 00:01:00.0000000

Exemplo otimizado com janela de tempo

Para otimizar essa consulta, podemos reescrevê-la para levar em conta a janela de tempo. A janela de tempo é expressa como uma chave de junção. Reescreva a consulta para que os valores de datetime sejam "discretizados" em buckets cujo tamanho é metade do tamanho da janela de tempo. Use equi-join para comparar os IDs do bucket.

A consulta encontra pares de eventos dentro da mesma sessão (SessionId) onde um evento 'A' é seguido por um evento 'B' dentro de 1 minuto. Ele projeta o ID da sessão, a hora de início do evento 'A' e a hora de término do evento 'B'.

let T = datatable(SessionId:string, EventType:string, Timestamp:datetime)
[
    '0', 'A', datetime(2017-10-01 00:00:00),
    '0', 'B', datetime(2017-10-01 00:01:00),
    '1', 'B', datetime(2017-10-01 00:02:00),
    '1', 'A', datetime(2017-10-01 00:03:00),
    '3', 'A', datetime(2017-10-01 00:04:00),
    '3', 'B', datetime(2017-10-01 00:10:00),
];
let lookupWindow = 1min;
let lookupBin = lookupWindow / 2.0;
T 
| where EventType == 'A'
| project SessionId, Start=Timestamp, TimeKey = bin(Timestamp, lookupBin)
| join kind=inner
    (
    T 
    | where EventType == 'B'
    | project SessionId, End=Timestamp,
              TimeKey = range(bin(Timestamp-lookupWindow, lookupBin),
                              bin(Timestamp, lookupBin),
                              lookupBin)
    | mv-expand TimeKey to typeof(datetime)
    ) on SessionId, TimeKey 
| where (End - Start) between (0min .. lookupWindow)
| project SessionId, Start, End 

Output

SessionId Início Fim
0 2017-10-01 00:00:00.0000000 2017-10-01 00:01:00.0000000

5 milhões de consultas de dados

A próxima consulta emula um extenso conjunto de dados de 5 milhões de registros e aproximadamente 1 milhão de IDs de sessão e executa a consulta com a técnica de janela de tempo.

let T = range x from 1 to 5000000 step 1
| extend SessionId = rand(1000000), EventType = rand(3), Time=datetime(2017-01-01)+(x * 10ms)
| extend EventType = case(EventType < 1, "A",
                          EventType < 2, "B",
                          "C");
let lookupWindow = 1min;
let lookupBin = lookupWindow / 2.0;
T 
| where EventType == 'A'
| project SessionId, Start=Time, TimeKey = bin(Time, lookupBin)
| join kind=inner
    (
    T 
    | where EventType == 'B'
    | project SessionId, End=Time, 
              TimeKey = range(bin(Time-lookupWindow, lookupBin), 
                              bin(Time, lookupBin),
                              lookupBin)
    | mv-expand TimeKey to typeof(datetime)
    ) on SessionId, TimeKey 
| where (End - Start) between (0min .. lookupWindow)
| project SessionId, Start, End 
| count 

Output

Contagem
3344