Sdílet prostřednictvím


Spojení s časovým oknem

Platí pro: ✅Microsoft FabricAzure Data ExplorerAzure MonitorMicrosoft Sentinel

Často je užitečné spojit se mezi dvěma velkými datovými sadami u některého klíče s vysokou kardinalitou, jako je ID operace nebo ID relace, a dále omezit záznamy na pravé straně ($right), které se musí shodovat s každým záznamem na levé straně ($left), a to přidáním omezení "časové vzdálenosti" mezi datetime sloupci vlevo a vpravo.

Výše uvedená operace se liší od obvyklé operace spojení, protože pro equi-join část párování klíče s vysokou kardinalitou mezi levou a pravou datovou sadou může systém také použít funkci vzdálenosti a použít ji k výrazně zrychlení spojení.

Poznámka

Funkce vzdálenosti se nechová jako rovnost (to znamená, že když jsou obě hodnoty dist(x;y) a dist(y;z) pravdivé, nenásleduje, že hodnota dist(x;z) je také pravdivá.) Někdy se to označuje jako "diagonální spojení".

Příklad identifikace sekvencí událostí bez časového intervalu

K identifikaci sekvencí událostí v relativně malém časovém intervalu používá tento příklad tabulku T s následujícím schématem:

  • SessionId: Sloupec typu string s ID korelace.
  • EventType: Sloupec typu string, který identifikuje typ události záznamu.
  • Timestamp: Sloupec typu datetime označuje, kdy došlo k události popsané záznamem.
Id relace Typ události Časová značka
0 A 2017-10-01T00:00:00Z
0 B 2017-10-01T00:01:00Z
1 B 2017-10-01T00:02:00Z
1 A 2017-10-01T00:03:00Z
3 A 2017-10-01T00:04:00Z
3 B 2017-10-01T00:10:00Z

Následující dotaz vytvoří datovou sadu a pak identifikuje všechna ID relací, ve kterých typ události A byl následovaný typem události B v rámci 1min časového intervalu.

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 

výstupní

Id relace Začínat Konec
0 2017-10-01 00:00:00.0000000 2017-10-01 00:01:00.0000000

Příklad optimalizovaný s časovým oknem

Abychom tento dotaz optimalizovali, můžeme ho přepsat tak, aby se zohlednil časový interval. Časové období se vyjadřuje jako klíč spojení. Přepište dotaz tak, aby hodnoty datetime byly "diskretizovány" do kbelíků, jejichž velikost je poloviční velikost časového intervalu. K porovnání ID kontejnerů použijte equi-join.

Dotaz najde dvojice událostí ve stejné relaci (SessionId), kde za událostí A následuje událost B do 1 minuty. Projektuje ID relace, počáteční čas události "A" a koncový čas události "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 

výstupní

Id relace Začínat Konec
0 2017-10-01 00:00:00.0000000 2017-10-01 00:01:00.0000000

Dotaz na 5 milionů dat

Další dotaz emuluje rozsáhlou datovou sadu 5M záznamů a přibližně 1M ID relací a spustí dotaz technikou časového intervalu.

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 

výstupní

Počítat
3344