Ingresso na janela de tempo
Aplica-se a: ✅Microsoft Fabric✅Azure Data Explorer✅Azure Monitor✅Microsoft 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 tipostring
com IDs de correlação. -
EventType
: Uma coluna do tipostring
que identifica o tipo de evento do registro. -
Timestamp
: Uma coluna do tipodatetime
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 |