Tijdvensterdeelname
Van toepassing op: ✅Microsoft Fabric✅Azure Data Explorer✅Azure Monitor✅Microsoft Sentinel-
Het is vaak handig om deel te nemen tussen twee grote gegevenssets op een sleutel met hoge kardinaliteit, zoals een bewerkings-id of een sessie-id, en de records aan de rechterkant ($right) die moeten overeenkomen met elke record aan de linkerkant ($left) door een beperking toe te voegen aan de 'tijdafstand' tussen datetime
kolommen aan de linkerkant en aan de rechterkant.
De bovenstaande bewerking verschilt van de gebruikelijke join-bewerking, omdat voor het equi-join
deel van het koppelen van de sleutel met hoge kardinaliteit tussen de linker- en rechtergegevenssets ook een afstandsfunctie kan worden toegepast en het systeem kan gebruiken om de join aanzienlijk te versnellen.
Notitie
Een afstandsfunctie gedraagt zich niet als gelijkheid (dus wanneer zowel dist(x,y) als dist(y,z) waar zijn, volgt deze niet dat dist(x,z) ook waar is.) Dit wordt soms een 'diagonale join' genoemd.
Voorbeeld voor het identificeren van gebeurtenisreeksen zonder tijdvenster
Voor het identificeren van gebeurtenisreeksen binnen een relatief klein tijdvenster gebruikt dit voorbeeld een tabel T
met het volgende schema:
-
SessionId
: een kolom van het typestring
met correlatie-id's. -
EventType
: een kolom van het typestring
waarmee het gebeurtenistype van de record wordt geïdentificeerd. -
Timestamp
: Een kolom van het typedatetime
geeft aan wanneer de gebeurtenis die door de record is beschreven.
SessionId | EventType | Tijdstempel |
---|---|---|
0 | Een | 2017-10-01T00:00:00Z |
0 | B | 2017-10-01T00:01:00Z |
1 | B | 2017-10-01T00:02:00Z |
1 | Een | 2017-10-01T00:03:00Z |
3 | Een | 2017-10-01T00:04:00Z |
3 | B | 2017-10-01T00:10:00Z |
De volgende query maakt de gegevensset en identificeert vervolgens alle sessie-id's waarin het gebeurtenistype A
werd gevolgd door een gebeurtenistype B
binnen een 1min
tijdvenster.
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
uitvoer
SessionId | Beginnen | Einde |
---|---|---|
0 | 2017-10-01 00:00:00.0000000 | 2017-10-01 00:01:00.0000000 |
Voorbeeld geoptimaliseerd met tijdvenster
Om deze query te optimaliseren, kunnen we deze opnieuw schrijven om rekening te houden met het tijdvenster. Het tijdvenster wordt uitgedrukt als een join-sleutel. Herschrijf de query zodat de datetime
waarden worden 'discretized' in buckets waarvan de grootte de helft van het tijdvenster is. Gebruik equi-join
om de bucket-id's te vergelijken.
De query zoekt paren gebeurtenissen binnen dezelfde sessie (SessionId) waarbij een A-gebeurtenis binnen 1 minuut wordt gevolgd door een B-gebeurtenis. Het projecteert de sessie-id, de begintijd van de gebeurtenis A en de eindtijd van de gebeurtenis 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
uitvoer
SessionId | Beginnen | Einde |
---|---|---|
0 | 2017-10-01 00:00:00.0000000 | 2017-10-01 00:01:00.0000000 |
5 miljoen gegevensquery
Met de volgende query wordt een uitgebreide gegevensset van 5M-records en ongeveer 1M Sessie-id's geëmuleerd en wordt de query uitgevoerd met de tijdvenstertechniek.
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
uitvoer
Tellen |
---|
3344 |