Spojení s časovým oknem
Platí pro: ✅Microsoft Fabric✅Azure Data Explorer✅Azure Monitor✅Microsoft 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 typustring
s ID korelace. -
EventType
: Sloupec typustring
, který identifikuje typ události záznamu. -
Timestamp
: Sloupec typudatetime
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 |