Compartir a través de


Combinación de período de tiempo

Se aplica a: ✅Microsoft FabricAzure Data ExplorerAzure MonitorMicrosoft Sentinel

A menudo resulta útil combinar entre dos conjuntos de datos grandes en alguna clave de cardinalidad alta, como un identificador de operación o un identificador de sesión, y limitar aún más los registros del lado derecho ($right) que deben coincidir con cada registro del lado izquierdo ($left) agregando una restricción en la "distancia de tiempo" entre datetime columnas de la izquierda y a la derecha.

La operación anterior difiere de la operación de combinación habitual, ya que para la equi-join parte de la coincidencia de la clave de alta cardinalidad entre los conjuntos de datos izquierdo y derecho, el sistema también puede aplicar una función de distancia y usarla para acelerar considerablemente la combinación.

Nota

Una función de distancia no se comporta como la igualdad (es decir, cuando tanto dist(x,y) como dist(y,z) son true, no sigue que dist(x,z) también sea true). Esto se conoce a veces como una "combinación diagonal".

Ejemplo para identificar secuencias de eventos sin período de tiempo

Para identificar secuencias de eventos dentro de un período de tiempo relativamente pequeño, en este ejemplo se usa una tabla T con el esquema siguiente:

  • SessionId: una columna de tipo string con identificadores de correlación.
  • EventType: columna de tipo string que identifica el tipo de evento del registro.
  • Timestamp: una columna de tipo datetime indica cuándo se produjo el evento descrito por el registro.
SessionId EventType Timestamp
0 Un 2017-10-01T00:00:00Z
0 B 2017-10-01T00:01:00Z
1 B 2017-10-01T00:02:00Z
1 Un 2017-10-01T00:03:00Z
3 Un 2017-10-01T00:04:00Z
3 B 2017-10-01T00:10:00Z

La consulta siguiente crea el conjunto de datos y, a continuación, identifica todos los identificadores de sesión en los que el tipo de evento A fue seguido de un tipo de evento B dentro de un período de tiempo de 1min.

Ejecutar el 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 salida

SessionId Empezar Fin
0 2017-10-01 00:00:00.0000000 2017-10-01 00:01:00.0000000

Ejemplo optimizado con ventana de tiempo

Para optimizar esta consulta, podemos volver a escribirla para tener en cuenta el período de tiempo. El período de tiempo de THe se expresa como una clave de combinación. Vuelva a escribir la consulta para que los valores de datetime sean "discretizados" en cubos cuyo tamaño sea la mitad del tamaño de la ventana de tiempo. Use equi-join para comparar los identificadores de cubo.

La consulta busca pares de eventos dentro de la misma sesión (SessionId) donde un evento "A" va seguido de un evento "B" en un minuto. Proyecta el identificador de sesión, la hora de inicio del evento "A" y la hora de finalización del evento "B".

Ejecutar el 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 salida

SessionId Empezar Fin
0 2017-10-01 00:00:00.0000000 2017-10-01 00:01:00.0000000

5 millones de consultas de datos

La siguiente consulta emula un amplio conjunto de datos de registros de 5M y aproximadamente 1M de identificadores de sesión y ejecuta la consulta con la técnica de período de tiempo.

Ejecutar el 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 salida

Contar
3344