Uso di hll() e tdigest()
Si supponga di voler calcolare il numero di utenti distinti ogni giorno negli ultimi sette giorni. È possibile eseguire summarize dcount(user)
una volta al giorno con un intervallo filtrato negli ultimi sette giorni. Questo metodo è inefficiente, perché ogni volta che il calcolo viene eseguito, è presente una sovrapposizione di sei giorni con il calcolo precedente. È anche possibile calcolare un'aggregazione per ogni giorno e quindi combinare queste aggregazioni. Questo metodo richiede di "ricordare" gli ultimi sei risultati, ma è molto più efficiente.
Le query di partizionamento come descritto sono facili per semplici aggregazioni, ad esempio count()
e sum()
. Può anche essere utile per aggregazioni complesse, ad esempio dcount()
e percentiles()
. Questo articolo illustra come Kusto supporti tali calcoli.
Negli esempi seguenti viene illustrato come usare e dimostrare che l'uso hll
/tdigest
di questi comandi è altamente efficiente in alcuni scenari:
Importante
I risultati di hll
, hll_if
, hll_merge
tdigest
, e tdigest_merge
sono oggetti di tipo dynamic
che possono quindi essere elaborati da altre funzioni (dcount_hll
, percentile_tdigest
percentiles_array_tdigest
, e percentrank_tdigest
). La codifica di questo oggetto potrebbe cambiare nel tempo (ad esempio, a causa di un aggiornamento software); Tuttavia, tali modifiche verranno eseguite in modo compatibile con le versioni precedenti, in modo da poter archiviare tali valori in modo permanente e farvi riferimento nelle query in modo affidabile.
Nota
In alcuni casi, gli oggetti dinamici generati dalle hll
tdigest
funzioni di aggregazione possono essere grandi e superare la proprietà MaxValueSize predefinita nei criteri di codifica. In tal caso, l'oggetto verrà inserito come Null.
Ad esempio, quando si mantiene l'output della hll
funzione con accuratezza livello 4, le dimensioni dell'oggetto hll
superano il valore predefinito di MaxValueSize, ovvero 1 MB.
Per evitare questo problema, modificare i criteri di codifica della colonna, come illustrato negli esempi seguenti.
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 |
L'inserimento di questo oggetto in una tabella prima di applicare questo tipo di criterio inserisce null:
.set-or-append MyTable <| range x from 1 to 1000000 step 1
| summarize hll(x,4)
MyTable
| project isempty(hll_x)
Output
Colonna 1 |
---|
1 |
Per evitare l'inserimento di null, usare il tipo di bigobject
criterio di codifica speciale , che esegue l'override di MaxValueSize
su 2 MB come indicato di seguito:
.alter column MyTable.hll_x policy encoding type='bigobject'
Inserimento di un valore nella stessa tabella precedente:
.set-or-append MyTable <| range x from 1 to 1000000 step 1
| summarize hll(x,4)
inserisce correttamente il secondo valore:
MyTable
| project isempty(hll_x)
Output
Colonna 1 |
---|
1 |
0 |
Esempio: Conteggio con timestamp bined
È presente una tabella, , PageViewsHllTDigest
contenente hll
i valori di Pages visualizzati in ogni ora. Si desidera che questi valori vengano binati in 12h
. Unire i hll
valori usando la hll_merge()
funzione di aggregazione, con il timestamp bined in 12h
. Utilizzare la funzione dcount_hll
per restituire il valore finale dcount
:
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 |
Per bin timestamp per 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 |
La stessa query può essere eseguita sui valori di tdigest
, che rappresentano l'oggetto BytesDelivered
in ogni ora:
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 |
Esempio: Tabella temporanea
I limiti di Kusto vengono raggiunti con set di dati troppo grandi, in cui è necessario eseguire query periodiche sul set di dati, ma eseguire le query regolari per calcolare percentile()
o dcount()
superare set di dati di grandi dimensioni.
Per risolvere questo problema, i dati appena aggiunti possono essere aggiunti a una tabella temporanea come hll
o valori usando hll()
quando l'operazione necessaria è o tdigest()
quando l'operazione necessaria è dcount
percentile usando set/append
o update policy
tdigest
. In questo caso, i risultati intermedi di o tdigest
vengono salvati in un altro set di dcount
dati, che deve essere inferiore a quello di destinazione di grandi dimensioni.
Per risolvere questo problema, i dati appena aggiunti possono essere aggiunti a una tabella temporanea come hll
o valori usando hll()
quando l'operazione necessaria è dcount
tdigest
. In questo caso, i risultati intermedi di vengono salvati in un altro set di dcount
dati, che deve essere inferiore a quello di destinazione di grandi dimensioni.
Quando è necessario ottenere i risultati finali di questi valori, le query possono usare hll
/tdigest
fusioni: . hll-merge()
/tdigest_merge()
Quindi, dopo aver ottenuto i valori uniti, percentile_tdigest()
/ dcount_hll()
può essere richiamato su questi valori uniti per ottenere il risultato finale di dcount
o percentile.
Supponendo che sia presente una tabella, PageViews, in cui i dati vengono inseriti ogni giorno, ogni giorno in cui si vuole calcolare il numero distinto di pagine visualizzate al minuto più tardi della data = datetime(2016-05-01 18:00:00.000000000).
Eseguire la query seguente:
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 |
Questa query aggrega tutti i valori ogni volta che si esegue questa query, ad esempio se si vuole eseguirla più volte al giorno.
Se si salvano i hll
valori e (ovvero i risultati intermedi di e tdigest
percentile) in una tabella temporanea, , PageViewsHllTDigest
usando un criterio di dcount
aggiornamento o i comandi set/accodamento, è possibile unire solo i valori e quindi usare dcount_hll
/percentile_tdigest
la query seguente:
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 | 84224 | 20056275 |
2016-05-02 00:00:00.0000000 | 83486 | 64135183 |
2016-05-03 00:00:00.0000000 | 72247 | 13685621 |
Questa query dovrebbe essere più efficiente, poiché viene eseguita su una tabella più piccola. In questo esempio la prima query viene eseguita su ~215M record, mentre la seconda esegue solo 32 record:
Esempio: Risultati intermedi
Query di conservazione. Si supponga di avere una tabella che riepiloga quando ogni pagina di Wikipedia è stata visualizzata (dimensioni di esempio è 10M) e si vuole trovare per ogni data1 data2 la percentuale di pagine esaminate in data1 e data2 relative alle pagine visualizzate in data1 (data1 < data2).
Il modo semplice usa operatori di join e riepilogo:
// 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
Giorno 1 | Giorno 2 | Percentuale |
---|---|---|
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 |
La query precedente ha richiesto circa 18 secondi.
Quando si usano le hll()
funzioni , hll_merge()
e dcount_hll()
, la query equivalente termina dopo circa 1,3 secondi e mostra che le funzioni accelerano la hll
query precedente per ~14 volte:
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
giorno1 | giorno2 | Percentuale |
---|---|---|
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 |
Nota
I risultati delle query non sono accurati del 100% a causa dell'errore delle hll
funzioni. Per altre informazioni sugli errori, vedere dcount()
.
Commenti e suggerimenti
https://aka.ms/ContentUserFeedback.
Presto disponibile: Nel corso del 2024 verranno gradualmente disattivati i problemi di GitHub come meccanismo di feedback per il contenuto e ciò verrà sostituito con un nuovo sistema di feedback. Per altre informazioni, vedereInvia e visualizza il feedback per