Compartilhar via


Junção da janela de tempo

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

Geralmente, é útil unir entre dois grandes conjuntos de dados em alguma chave de alta cardinalidade, como uma ID de operação ou uma 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 à "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 da 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.

Nota

Uma função de distância não se comporta como igualdade (ou seja, quando dist(x,y) e dist(y,z) são verdadeiras, ela não segue que dist(x,z) também é verdadeiro.) Às vezes, isso é chamado de "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 o evento descrito pelo registro ocorreu.
SessionId EventType Timestamp
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 identifica todas as IDs de sessão nas quais o tipo de evento A foi seguido por um tipo de evento B dentro de uma janela de tempo 1min.

executar o de consulta

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 

de saída

SessionId Começar Fim
0 2017-10-01 00:00:00.0000000 2017-10-01 00:01:00.0000000

Exemplo otimizado com a janela de tempo

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

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

executar o de consulta

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 

de saída

SessionId Começar Fim
0 2017-10-01 00:00:00.0000000 2017-10-01 00:01:00.0000000

Consulta de dados de 5 milhões

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

executar o de consulta

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 

de saída

Contar
3344
  • operador de junção