Freigeben über


Verwenden von „hll()“ und „tdigest()“

Gilt für: ✅Microsoft Fabric✅Azure Data ExplorerAzure MonitorMicrosoft Sentinel

Angenommen, Sie möchten die Anzahl der eindeutigen Benutzer jeden Tag in den letzten sieben Tagen berechnen. Sie können einmal pro Tag mit einer Spanne nach den letzten sieben Tagen ausgeführt summarize dcount(user) werden. Diese Methode ist ineffizient, da jedes Mal, wenn die Berechnung ausgeführt wird, eine Sechs-Tage-Überlappung mit der vorherigen Berechnung besteht. Sie können auch ein Aggregat für jeden Tag berechnen und diese Aggregate dann kombinieren. Diese Methode erfordert, dass Sie sich die letzten sechs Ergebnisse merken, aber es ist viel effizienter.

Partitionierungsabfragen wie beschrieben sind für einfache Aggregate wie count() z. B. und sum(). Es kann auch für komplexe Aggregate nützlich sein, z dcount() . B. und percentiles(). In diesem Artikel wird erläutert, wie Kusto solche Berechnungen unterstützt.

In den folgenden Beispielen wird gezeigt, wie Sie diese Befehle verwenden hll/tdigest und demonstrieren können, die in einigen Szenarien sehr leistungsfähig sind:

Wichtig

Die Ergebnisse von hll, hll_if, hll_merge, tdigestund tdigest_merge sind Objekte vom Typdynamic, die dann von anderen Funktionen verarbeitet werden können (dcount_hll, percentile_tdigest, und percentiles_array_tdigestpercentrank_tdigest). Die Codierung dieses Objekts kann sich im Laufe der Zeit ändern (z. B. aufgrund eines Softwareupgrades); Solche Änderungen erfolgen jedoch abwärtskompatibel, sodass man solche Werte dauerhaft speichern und zuverlässig in Abfragen referenzieren kann.

Hinweis

In einigen Fällen können die dynamischen Objekte, die von den hll tdigest Aggregatfunktionen generiert werden, groß sein und die Standardmäßige MaxValueSize-Eigenschaft in der Codierungsrichtlinie überschreiten. Wenn ja, wird das Objekt als NULL aufgenommen. Wenn sie beispielsweise die Ausgabe der hll Funktion mit Genauigkeitsebene 4 beibehalten, überschreitet die Größe des hll Objekts die MaxValueSize-Standardgröße, die 1 MB ist. Um dieses Problem zu vermeiden, ändern Sie die Codierungsrichtlinie der Spalte, wie in den folgenden Beispielen gezeigt.

range x from 1 to 1000000 step 1
| summarize hll(x,4)
| project sizeInMb = estimate_data_size(hll_x) / pow(1024,2)

Output

sizeInMb
1.0000524520874

Wenn Sie dieses Objekt in eine Tabelle aufnehmen, bevor Sie diese Art von Richtlinie anwenden, wird NULL aufgenommen:

.set-or-append MyTable <| range x from 1 to 1000000 step 1
| summarize hll(x,4)
MyTable
| project isempty(hll_x)

Output

Spalte1
1

Verwenden Sie den speziellen Codierungsrichtlinientyp bigobject, der die MaxValueSize Codierung auf 2 MB überschreibt, um null zu vermeiden:

.alter column MyTable.hll_x policy encoding type='bigobject'

Aufnehmen eines Werts jetzt zur gleichen Tabelle oben:

.set-or-append MyTable <| range x from 1 to 1000000 step 1
| summarize hll(x,4)

nimmt den zweiten Wert erfolgreich ein:

MyTable
| project isempty(hll_x)

Output

Spalte1
1
0

Beispiel: Anzahl mit binniertem Zeitstempel

Es gibt eine Tabelle, die Werte von Seiten enthälthll, PageViewsHllTDigestdie in jeder Stunde angezeigt werden. Sie möchten, dass diese Werte in einen Binned -Wert 12humgewandelt werden sollen. Führen Sie die hll Werte mithilfe der hll_merge() Aggregatfunktion zusammen, wobei der Zeitstempel mit dem binniert ist 12h. Verwenden Sie die Funktion dcount_hll , um den endgültigen dcount Wert zurückzugeben:

PageViewsHllTDigest
| summarize merged_hll = hll_merge(hllPage) by bin(Timestamp, 12h)
| project Timestamp , dcount_hll(merged_hll)

Output

Timestamp dcount_hll_merged_hll
2016-05-01 12:00:00.0000000 20056275
2016-05-02 00:00:00.0000000 38797623
2016-05-02 12:00:00.0000000 39316056
2016-05-03 00:00:00.0000000 13685621

Zum Bin-Zeitstempel für 1d:

PageViewsHllTDigest
| summarize merged_hll = hll_merge(hllPage) by bin(Timestamp, 1d)
| project Timestamp , dcount_hll(merged_hll)

Output

Timestamp dcount_hll_merged_hll
2016-05-01 00:00:00.0000000 20056275
2016-05-02 00:00:00.0000000 64135183
2016-05-03 00:00:00.0000000 13685621

Dieselbe Abfrage kann über die Werte von tdigest, die BytesDelivered die in jeder Stunde darstellen, durchgeführt werden:

PageViewsHllTDigest
| summarize merged_tdigests = merge_tdigest(tdigestBytesDel) by bin(Timestamp, 12h)
| project Timestamp , percentile_tdigest(merged_tdigests, 95, typeof(long))

Output

Timestamp percentile_tdigest_merged_tdigests
2016-05-01 12:00:00.0000000 170200
2016-05-02 00:00:00.0000000 152975
2016-05-02 12:00:00.0000000 181315
2016-05-03 00:00:00.0000000 146817

Beispiel: Temporäre Tabelle

Kusto-Grenzwerte werden mit Zu großen Datasets erreicht, bei denen Sie regelmäßige Abfragen über das Dataset ausführen müssen, aber die regulären Abfragen ausführen, um große Datasets zu berechnen percentile() oder dcount() zu übersteigen.

Um dieses Problem zu lösen, können neu hinzugefügte Daten zu einer temporären Tabelle als oder Werte hll() hinzugefügt werden, die verwendet werden, wenn der erforderliche Vorgang oder tdigest() dcount der erforderliche Vorgang per Quantil verwendet set/append oder update policyverwendet tdigest wird.hll In diesem Fall werden die Zwischenergebnisse eines dcount anderen Datasets gespeichert oder tdigest in einem anderen Dataset gespeichert, das kleiner als das zielgroße sein sollte.

Um dieses Problem zu lösen, können neu hinzugefügte Daten zu einer temporären Tabelle als hll oder tdigest Werte hll() hinzugefügt werden, die verwendet werden, wenn der erforderliche Vorgang ist dcount. In diesem Fall werden die Zwischenergebnisse dcount in einem anderen Dataset gespeichert, das kleiner als das zielgroße sein sollte.

Wenn Sie die endgültigen Ergebnisse dieser Werte abrufen müssen, können die Abfragen Fusionen verwendenhll/tdigest: . hll-merge()/tdigest_merge() Nach dem Abrufen der zusammengeführten Werte können diese zusammengeführten Werte aufgerufen werden, percentile_tdigest() / dcount_hll() um das Endergebnis von dcount oder Quantils zu erhalten.

Vorausgesetzt, es gibt eine Tabelle, PageViews, in die Daten täglich aufgenommen werden, jeden Tag, an dem Sie die unterschiedliche Anzahl von Seiten berechnen möchten, die pro Minute angezeigt werden als Datum = datetime(2016-05-01 18:00:00.00.000000).

Führen Sie die folgende Abfrage aus:

PageViews
| where Timestamp > datetime(2016-05-01 18:00:00.0000000)
| summarize percentile(BytesDelivered, 90), dcount(Page,2) by bin(Timestamp, 1d)

Output

Timestamp percentile_BytesDelivered_90 dcount_Page
2016-05-01 00:00:00.0000000 83634 20056275
2016-05-02 00:00:00.0000000 82770 64135183
2016-05-03 00:00:00.0000000 72920 13685621

Diese Abfrage aggregiert alle Werte jedes Mal, wenn Sie diese Abfrage ausführen (z. B. wenn Sie sie mehrmals täglich ausführen möchten).

Wenn Sie die hll Zwischenergebnisse und Quantilswerte dcount in einer temporären Tabelle speichern, PageViewsHllTDigestindem Sie eine Aktualisierungsrichtlinie verwenden oder Befehle zum Festlegen/Anfügen verwenden, können Sie nur die Werte zusammenführen und dann die folgende Abfrage verwendendcount_hll/percentile_tdigest:tdigest

PageViewsHllTDigest
| summarize  percentile_tdigest(merge_tdigest(tdigestBytesDel), 90), dcount_hll(hll_merge(hllPage)) by bin(Timestamp, 1d)

Output

Timestamp percentile_tdigest_merge_tdigests_tdigestBytesDel dcount_hll_hll_merge_hllPage
2016-05-01 00:00:00.0000000 84,224 20056275
2016-05-02 00:00:00.0000000 83486 64135183
2016-05-03 00:00:00.0000000 72247 13685621

Diese Abfrage sollte leistungsfähiger sein, da sie über eine kleinere Tabelle ausgeführt wird. In diesem Beispiel wird die erste Abfrage über ~215M-Datensätze ausgeführt, während die zweite über nur 32 Datensätze ausgeführt wird:

Beispiel: Zwischenergebnisse

Die Aufbewahrungsabfrage. Angenommen, Sie haben eine Tabelle, die zusammenfasst, wann jede Wikipedia-Seite angezeigt wurde (Beispielgröße ist 10M), und Sie möchten für jedes Datum1 Datum2 den Prozentsatz der Seiten ermitteln, die in Datum1 und Datum2 relativ zu den am Datum1 angezeigten Seiten (Datum1 < Datum2) überprüft wurden.

Die triviale Methode verwendet Verknüpfungs- und Zusammenfassungsoperatoren:

// Get the total pages viewed each day
let totalPagesPerDay = PageViewsSample
| summarize by Page, Day = startofday(Timestamp)
| summarize count() by Day;
// Join the table to itself to get a grid where 
// each row shows foreach page1, in which two dates
// it was viewed.
// Then count the pages between each two dates to
// get how many pages were viewed between date1 and date2.
PageViewsSample
| summarize by Page, Day1 = startofday(Timestamp)
| join kind = inner
(
    PageViewsSample
    | summarize by Page, Day2 = startofday(Timestamp)
)
on Page
| where Day2 > Day1
| summarize count() by Day1, Day2
| join kind = inner
    totalPagesPerDay
on $left.Day1 == $right.Day
| project Day1, Day2, Percentage = count_*100.0/count_1

Output

Tag1 Tag2 Prozentwert
2016-05-01 00:00:00.0000000 2016-05-02 00:00:00.0000000 34.0645725975255
2016-05-01 00:00:00.0000000 2016-05-03 00:00:00.0000000 16.618368960101
2016-05-02 00:00:00.0000000 2016-05-03 00:00:00.0000000 14.6291376489636

Die obige Abfrage dauerte ca. 18 Sekunden.

Wenn Sie die hll()hll_merge()Funktionen und Funktionen dcount_hll() verwenden, endet die entsprechende Abfrage nach ~1,3 Sekunden und zeigt, dass die hll Funktionen die oben genannte Abfrage um ~14 Mal beschleunigen:

let Stats=PageViewsSample | summarize pagehll=hll(Page, 2) by day=startofday(Timestamp); // saving the hll values (intermediate results of the dcount values)
let day0=toscalar(Stats | summarize min(day)); // finding the min date over all dates.
let dayn=toscalar(Stats | summarize max(day)); // finding the max date over all dates.
let daycount=tolong((dayn-day0)/1d); // finding the range between max and min
Stats
| project idx=tolong((day-day0)/1d), day, pagehll
| mv-expand pidx=range(0, daycount) to typeof(long)
// Extend the column to get the dcount value from hll'ed values for each date (same as totalPagesPerDay from the above query)
| extend key1=iff(idx < pidx, idx, pidx), key2=iff(idx < pidx, pidx, idx), pages=dcount_hll(pagehll)
// For each two dates, merge the hll'ed values to get the total dcount over each two dates, 
// This helps to get the pages viewed in both date1 and date2 (see the description below about the intersection_size)
| summarize (day1, pages1)=arg_min(day, pages), (day2, pages2)=arg_max(day, pages), union_size=dcount_hll(hll_merge(pagehll)) by key1, key2
| where day2 > day1
// To get pages viewed in date1 and also date2, look at the merged dcount of date1 and date2, subtract it from pages of date1 + pages on date2.
| project pages1, day1,day2, intersection_size=(pages1 + pages2 - union_size)
| project day1, day2, Percentage = intersection_size*100.0 / pages1

Output

Tag1 Tag 2 Prozentwert
2016-05-01 00:00:00.0000000 2016-05-02 00:00:00.0000000 33.2298494510578
2016-05-01 00:00:00.0000000 2016-05-03 00:00:00.0000000 16.9773830213667
2016-05-02 00:00:00.0000000 2016-05-03 00:00:00.0000000 14.5160020350006

Hinweis

Die Ergebnisse der Abfragen sind aufgrund des Fehlers der hll Funktionen nicht 100 % genau. Weitere Informationen zu den Fehlern finden Sie unter dcount().