Procedure consigliate per le query di Linguaggio di query Kusto

Di seguito sono descritte alcune procedure consigliate da seguire per velocizzare l'esecuzione delle query.

In breve

Azione Uso Non usare Note
Ridurre la quantità di dati sottoposti a query Usare meccanismi come l'operatore where per ridurre la quantità di dati elaborati. Vedere di seguito per modi efficienti per ridurre la quantità di dati elaborati.
Evitare di usare riferimenti qualificati ridondanti Quando si fa riferimento alle entità locali, usare il nome non qualificato. Per altre informazioni sull'argomento, vedere di seguito.
datetime Colonne Usare il datetime tipo di dati. Non usare il long tipo di dati. Nelle query non usare funzioni di conversione tempo unix, ad esempio unixtime_milliseconds_todatetime(). Usare invece criteri di aggiornamento per convertire il tempo unix nel tipo di dati durante l'inserimento datetime .
Operatori di stringa Usare l'operatore has Non usare contains Per la ricerca di token completi has funziona meglio, perché non cerca le sottostringhe.
Operatori con distinzione tra maiuscole e minuscole Utilizzare ==. Non usare =~ Usare gli operatori con distinzione tra maiuscole e minuscole quando possibile.
Utilizzare in. Non usare in~
Utilizzare contains_cs. Non usare contains Se si può usare has/has_cs invece di contains/contains_cs, è ancora meglio.
Ricerca di testo Cercare in una colonna specifica Non usare * * esegue una ricerca full-text in tutte le colonne.
Estrarre campi da oggetti dinamici su milioni di righe Materializzare la colonna in fase di inserimento se la maggior parte delle query estrae campi da oggetti dinamici su milioni di righe. In questo modo si paga una sola volta per l'estrazione delle colonne.
Cercare chiavi/valori rari negli oggetti dinamici Utilizzare MyTable | where DynamicColumn has "Rare value" | where DynamicColumn.SomeKey == "Rare value". Non usare MyTable | where DynamicColumn.SomeKey == "Rare value" In questo modo, si filtrano la maggior parte dei record e si esegue l'analisi JSON solo del resto.
Istruzione let con un valore che viene usato più volte Usare la funzione materialize() Per altre informazioni su come usare materialize(), vedere materialize(). Per altre informazioni, vedere Ottimizzare le query che usano espressioni denominate.
Applicare conversioni su più di 1 miliardo di record Rimodellare la query per ridurre la quantità di dati inseriti nella conversione. Se possibile, evitare di convertire grandi quantità di dati.
Nuove query Usare limit [small number] o count alla fine. L'esecuzione di query non in uscita su set di dati sconosciuti può restituire I GB dei risultati da restituire al client, causando una risposta lenta e un cluster occupato.
Confronti senza distinzione tra maiuscole e minuscole Utilizzare Col =~ "lowercasestring". Non usare tolower(Col) == "lowercasestring"
Confrontare dati già in lettere minuscole (o maiuscole) Col == "lowercasestring" (o Col == "UPPERCASESTRING") Evitare di usare confronti che non fanno distinzione tra maiuscole e minuscole.
Applicazione di filtri alle colonne Applicare un filtro su una colonna della tabella. Non applicare filtri su una colonna calcolata.
Utilizzare T | where predicate(*Expression*). Non usare T | extend _value = *Expression* | where predicate(_value)
Operatore summarize Usare hint.shufflekey=<key> quando l'operatore group by keys di riepilogo è con cardinalità elevata. La cardinalità elevata è idealmente superiore a 1 milione.
Operatore join Selezionare come prima tabella quella con il minor numero di righe (all'estrema sinistra nella query).
Usare in invece di sinistra join semi per filtrare in base a una singola colonna.
Join tra cluster In caso di join tra cluster, eseguire la query sul lato "destro" del join, dove si trova la maggior parte dei dati.
Join quando il lato sinistro è di dimensioni ridotte e il lato destro è grande Usare hint.strategy=broadcast Small fa riferimento a un massimo di 100 MB di dati.
Join quando il lato destro è piccolo e sinistro è grande Usare l'operatore di ricerca anziché l'operatorejoin Se il lato destro della ricerca è maggiore di diverse decine di MB, la query avrà esito negativo.
Join quando entrambi i lati sono troppo grandi Usare hint.shufflekey=<key> Usare quando la chiave di join ha una cardinalità elevata.
Estrarre valori in una colonna con stringhe che condividono lo stesso formato o modello Usare l'operatore parse Non usare più istruzioni extract(). Ad esempio, valori come "Time = <time>, ResourceId = <resourceId>, Duration = <duration>, ...."
Funzione extract() Usare quando le stringhe analizzate non hanno tutte lo stesso formato o modello. Estrarre i valori necessari tramite REGEX.
Funzione materialize() Eseguire il push di tutti gli operatori possibili che riducono il set di dati materializzato e mantengono comunque la semantica della query. Ad esempio, applicare filtri o proiettare solo le colonne necessarie. Per altre informazioni, vedere Ottimizzare le query che usano espressioni denominate.
Usare viste materializzate Usare viste materializzate per archiviare aggregazioni comunemente usate. Preferisce usare la funzione solo per eseguire query materialized_view() sulla parte materializzata materialized_view('MV')

Ridurre la quantità di dati elaborati

Le prestazioni di una query dipendono direttamente dalla quantità di dati da elaborare. I dati meno elaborati, la query più rapida e il minor numero di risorse che utilizza. Pertanto, la procedura consigliata più importante consiste nel strutturare la query in modo da ridurre la quantità di dati elaborati.

Nota

Nella discussione seguente, è importante tenere presente il concetto di selettività dei filtri. La selettività è la percentuale dei record che vengono filtrati quando si filtra in base a un predicato. Un predicato altamente selettivo significa che solo una manciata di record rimane dopo aver applicato il predicato, riducendo la quantità di dati che devono essere quindi elaborati in modo efficace.

In ordine di importanza:

  • Solo tabelle di riferimento i cui dati sono necessari dalla query. Ad esempio, quando si usa l'operatore union con riferimenti alla tabella con caratteri jolly, è preferibile da un punto di vista delle prestazioni per fare riferimento solo a una manciata di tabelle, anziché usare un carattere jolly (*) per fare riferimento a tutte le tabelle e quindi filtrare i dati usando un predicato sul nome della tabella di origine.

  • Sfruttare l'ambito dati di una tabella se la query è rilevante solo per un ambito specifico. La funzione table() offre un modo efficiente per eliminare i dati definendolo in base ai criteri di memorizzazione nella cache (parametro DataScope ).

  • Applicare immediatamente l'operatore where di query che segue i riferimenti alla tabella.

  • Quando si usa l'operatore di query, l'uso where predefinito dell'ordine dei predicati (in un singolo operatore o con un numero di operatori consecutivi, non importa quale) può avere un effetto significativo sulle prestazioni della query, come illustrato di seguito.

  • Applicare prima i predicati di partizione intera. Ciò significa che i predicati che usano la funzione extent_id() devono essere applicati prima, come sono predicati che usano la funzione extent_tags() e i predicati che sono molto selettivi sulle partizioni di dati della tabella (se definito).

  • Applicare quindi predicati che agiscono sulle datetime colonne di tabella. Kusto include un indice molto efficiente su tali colonne, spesso eliminando completamente le partizioni di dati intere senza dover accedere a tali partizioni.

  • Applicare quindi predicati che agiscono su string e dynamic colonne, soprattutto tali predicati che si applicano a livello di termine. I predicati devono essere ordinati in base alla selettività ( ad esempio, la ricerca di un ID utente quando ci sono milioni di utenti è molto selettiva e in genere è una ricerca di termini per cui l'indice è molto efficiente).

  • Applicare quindi predicati selettivi e basati su colonne numeriche.

  • Infine, per le query che analizzano i dati di una colonna di tabella ,ad esempio per i predicati come 'contiene "@!@!" che non dispongono di termini e non possono trarre vantaggio dall'indicizzazione, ordinare i predicati in modo che i predicati che analizzano le colonne con meno dati saranno prima. Ciò riduce la necessità di decompressione e analisi di colonne di grandi dimensioni.

Evitare di usare riferimenti qualificati ridondanti

Le entità, ad esempio tabelle e viste materializzate, vengono a cui si fa riferimento per nome. Ad esempio, la tabella può essere fatto riferimento come semplicemente T (il nome non qualificato) o usando un qualificatore di database (ad esempio, quando la tabella T si trova in un database denominato DB) o usando un nome completo (ad esempio database("DB").Tcluster("X.Y.kusto.windows.net").database("DB").T).

È consigliabile evitare di usare le qualifiche dei nomi quando sono ridondanti, per i motivi seguenti:

  1. I nomi non qualificati sono più facili da identificare (per un lettore umano) come appartenenti all'ambito del database.

  2. I riferimenti alle entità di ambito del database sono sempre più veloci e in alcuni casi molto più veloci, quindi le entità appartenenti ad altri database (soprattutto quando questi database si trovano in un cluster diverso). Evitare nomi qualificati aiuta il lettore a fare la cosa giusta.

Nota

Non si tratta di dire che i nomi qualificati sono cattivi per le prestazioni. Kusto, infatti, è in grado nella maggior parte dei casi di identificare quando un nome completo fa riferimento a un'entità appartenente all'ambito del database e alla query "short-circuit" in modo che non venga considerata come query tra cluster. Tuttavia, è consigliabile non basarsi su questo, se non necessario, per i motivi specificati in precedenza.