Ottimizzare le query di log in Monitoraggio di Azure

I log di Monitoraggio di Azure usano Azure Esplora dati per archiviare i dati di log ed eseguire query per l'analisi dei dati. Crea, gestisce e gestisce automaticamente i cluster di Esplora dati di Azure e li ottimizza per il carico di lavoro di analisi dei log. Quando si esegue una query, viene ottimizzata e indirizzata al cluster di Azure Esplora dati appropriato che archivia i dati dell'area di lavoro.

I log di Monitoraggio di Azure e Azure Esplora dati usano molti meccanismi di ottimizzazione automatica delle query. Le ottimizzazioni automatiche offrono un aumento significativo, ma in alcuni casi è possibile migliorare notevolmente le prestazioni delle query. Questo articolo illustra le considerazioni sulle prestazioni e diverse tecniche per risolverle.

La maggior parte delle tecniche è comune alle query eseguite direttamente in Azure Esplora dati e nei log di Monitoraggio di Azure. Vengono illustrate anche diverse considerazioni univoche per i log di Monitoraggio di Azure. Per altri suggerimenti per l'ottimizzazione di Azure Esplora dati, vedere Procedure consigliate per le query.

Le query ottimizzate:

  • Eseguire più velocemente e ridurre la durata complessiva dell'esecuzione della query.
  • Possibilità di limitare o rifiutare un numero minore di richieste.

Prestare particolare attenzione alle query usate per l'utilizzo ricorrente e simultaneo, ad esempio dashboard, avvisi, App per la logica di Azure e Power BI. L'impatto di una query inefficace in questi casi è sostanziale.

Ecco una procedura dettagliata per l'ottimizzazione delle query.

Riquadro Dettagli query

Dopo aver eseguito una query in Log Analytics, selezionare Dettagli query nell'angolo inferiore destro della schermata per aprire il riquadro Dettagli query. Questo riquadro mostra i risultati di diversi indicatori di prestazioni per la query. Questi indicatori di prestazioni sono descritti nella sezione seguente.

Screenshot that shows the Query Details pane in Azure Monitor Log Analytics.

Indicatori di prestazioni delle query

Per ogni query eseguita sono disponibili gli indicatori di prestazioni delle query seguenti:

  • CPU totale: calcolo complessivo usato per elaborare la query in tutti i nodi di calcolo. Rappresenta il tempo usato per il calcolo, l'analisi e il recupero dei dati.
  • Dati usati per la query elaborata: dati complessivi a cui è stato eseguito l'accesso per elaborare la query. Influenzato dalle dimensioni della tabella di destinazione, dall'intervallo di tempo usato, dai filtri applicati e dal numero di colonne a cui si fa riferimento.
  • Intervallo di tempo della query elaborata: distanza tra i dati più recenti e i dati meno recenti a cui è stato eseguito l'accesso per elaborare la query. Influenzato dall'intervallo di tempo esplicito specificato per la query.
  • Età dei dati elaborati: intervallo tra ora e i dati meno recenti a cui è stato eseguito l'accesso per elaborare la query. Influisce notevolmente sull'efficienza del recupero dei dati.
  • Numero di aree di lavoro: numero di aree di lavoro a cui è stato eseguito l'accesso durante l'elaborazione delle query in base alla selezione implicita o esplicita.
  • Numero di aree: numero di aree a cui è stato eseguito l'accesso durante l'elaborazione delle query in base alla selezione implicita o esplicita delle aree di lavoro. Le query in più aree sono molto meno efficienti e gli indicatori di prestazioni presentano una copertura parziale.
  • Parallelismo: indica quanto il sistema è stato in grado di eseguire questa query su più nodi. Rilevante solo per le query con un utilizzo elevato della CPU. Influenzato dall'utilizzo di funzioni e operatori specifici.

CPU totale

CPU di calcolo effettiva investita per elaborare questa query in tutti i nodi di elaborazione delle query. Poiché la maggior parte delle query viene eseguita su un numero elevato di nodi, questo totale in genere sarà molto più grande della durata impiegato dalla query per l'esecuzione.

Una query che usa più di 100 secondi di CPU viene considerata una query che utilizza risorse eccessive. Una query che usa più di 1.000 secondi di CPU viene considerata una query offensiva e potrebbe essere limitata.

Il tempo di elaborazione delle query viene impiegato per:

  • Recupero dei dati: il recupero dei dati precedenti utilizzerà più tempo rispetto al recupero dei dati recenti.
  • Elaborazione dati: logica e valutazione dei dati.

Oltre al tempo impiegato nei nodi di elaborazione delle query, i log di Monitoraggio di Azure impiegano tempo in:

  • Autenticare l'utente e verificare che sia autorizzato ad accedere a questi dati.
  • Individuazione dell'archivio dati.
  • Analisi della query.
  • Allocazione dei nodi di elaborazione delle query.

Questa volta non è incluso nel tempo totale della CPU della query.

Filtro anticipato dei record prima dell'uso di funzioni CPU elevate

Alcuni comandi e funzioni di query sono pesanti nel consumo di CPU. Questo caso è particolarmente vero per i comandi che analizzano JSON e XML o estraggono espressioni regolari complesse. Tale analisi può verificarsi in modo esplicito tramite funzioni parse_json() o parse_xml() o in modo implicito quando fa riferimento a colonne dinamiche.

Queste funzioni usano la CPU in proporzione al numero di righe che elaborano. L'ottimizzazione più efficiente consiste nell'aggiungere where condizioni nelle prime fasi della query. In questo modo, possono filtrare il maggior numero possibile di record prima dell'esecuzione della funzione a elevato utilizzo di CPU.

Ad esempio, le query seguenti producono esattamente lo stesso risultato. Ma il secondo è il più efficiente perché la condizione where prima dell'analisi esclude molti record:

//less efficient
SecurityEvent
| extend Details = parse_xml(EventData)
| extend FilePath = tostring(Details.UserData.RuleAndFileData.FilePath)
| extend FileHash = tostring(Details.UserData.RuleAndFileData.FileHash)
| where FileHash != "" and FilePath !startswith "%SYSTEM32"  // Problem: irrelevant results are filtered after all processing and parsing is done
| summarize count() by FileHash, FilePath
//more efficient
SecurityEvent
| where EventID == 8002 //Only this event have FileHash
| where EventData !has "%SYSTEM32" //Early removal of unwanted records
| extend Details = parse_xml(EventData)
| extend FilePath = tostring(Details.UserData.RuleAndFileData.FilePath)
| extend FileHash = tostring(Details.UserData.RuleAndFileData.FileHash)
| where FileHash != "" and FilePath !startswith "%SYSTEM32"  // exact removal of results. Early filter is not accurate enough
| summarize count() by FileHash, FilePath
| where FileHash != "" // No need to filter out %SYSTEM32 here as it was removed before

Evitare di usare le clausole where valutate

Le query che contengono clausole where in una colonna valutata anziché su colonne fisicamente presenti nel set di dati perdono efficienza. L'applicazione di filtri alle colonne valutate impedisce alcune ottimizzazioni di sistema quando vengono gestiti set di dati di grandi dimensioni.

Ad esempio, le query seguenti producono esattamente lo stesso risultato. Ma il secondo è più efficiente perché la condizione where fa riferimento a una colonna predefinita:

//less efficient
Syslog
| extend Msg = strcat("Syslog: ",SyslogMessage)
| where  Msg  has "Error"
| count 
//more efficient
Syslog
| where  SyslogMessage  has "Error"
| count 

In alcuni casi, la colonna valutata viene creata in modo implicito dal motore di elaborazione query perché il filtro non viene eseguito solo sul campo:

//less efficient
SecurityEvent
| where tolower(Process) == "conhost.exe"
| count 
//more efficient
SecurityEvent
| where Process =~ "conhost.exe"
| count 

Usare comandi e dimensioni di aggregazione efficaci in summarize e join

Alcuni comandi di aggregazione, ad esempio max(), sum(), count() e avg() hanno un impatto ridotto sulla CPU a causa della logica. Altri comandi sono più complessi e includono euristica e stime che consentono di eseguirli in modo efficiente. Ad esempio, dcount() usa l'algoritmo HyperLogLog per fornire una stima di chiusura a un conteggio distinto di set di dati di grandi dimensioni senza contare effettivamente ogni valore.

Le funzioni percentili eseguono approssimazioni simili usando l'algoritmo percentile di classificazione più vicino. Diversi comandi includono parametri facoltativi per ridurre l'impatto. Ad esempio, la funzione makeset() ha un parametro facoltativo per definire la dimensione massima del set, che influisce in modo significativo sulla CPU e sulla memoria.

I comandi join e riepilogo possono causare un utilizzo elevato della CPU durante l'elaborazione di un set di dati di grandi dimensioni. La complessità è direttamente correlata al numero di valori possibili, definiti cardinalità, delle colonne usate come by in summarize o come join attributi. Per la spiegazione e l'ottimizzazione di e summarize, vedere gli articoli della join documentazione e i suggerimenti per l'ottimizzazione.

Ad esempio, le query seguenti producono esattamente lo stesso risultato perché CounterPath è sempre mappato uno a uno a CounterName e ObjectName. Il secondo è più efficiente perché la dimensione di aggregazione è più piccola:

//less efficient
Perf
| summarize avg(CounterValue) 
by CounterName, CounterPath, ObjectName
//make the group expression more compact improve the performance
Perf
| summarize avg(CounterValue), any(CounterName), any(ObjectName) 
by CounterPath

L'utilizzo della CPU può anche essere influenzato da where condizioni o colonne estese che richiedono un utilizzo intensivo del calcolo. Tutti i confronti di stringhe semplici, ad esempio equal == e startswith, hanno approssimativamente lo stesso impatto sulla CPU. Le corrispondenze di testo avanzate hanno un impatto maggiore. In particolare, l'operatore has è più efficiente dell'operatore contains . A causa delle tecniche di gestione delle stringhe, è più efficiente cercare stringhe con più di quattro caratteri rispetto alle stringhe brevi.

Ad esempio, le query seguenti producono risultati simili, a seconda dei Computer criteri di denominazione. Ma il secondo è più efficiente:

//less efficient – due to filter based on contains
Heartbeat
| where Computer contains "Production" 
| summarize count() by ComputerIP 
//less efficient – due to filter based on extend
Heartbeat
| extend MyComputer = Computer
| where MyComputer startswith "Production" 
| summarize count() by ComputerIP 
//more efficient
Heartbeat
| where Computer startswith "Production" 
| summarize count() by ComputerIP 

Nota

Questo indicatore presenta solo la CPU dal cluster immediato. In una query in più aree rappresenta solo una delle aree. In una query su più aree di lavoro potrebbe non includere tutte le aree di lavoro.

Evitare l'analisi XML e JSON completa quando funziona l'analisi delle stringhe

L'analisi completa di un oggetto XML o JSON potrebbe utilizzare risorse di CPU e memoria elevate. In molti casi, quando sono necessari solo uno o due parametri e gli oggetti XML o JSON sono semplici, è più facile analizzarli come stringhe. Usare l'operatore parse o altre tecniche di analisi del testo. L'aumento delle prestazioni sarà più significativo perché aumenta il numero di record nell'oggetto XML o JSON. È essenziale quando il numero di record raggiunge decine di milioni.

Ad esempio, la query seguente restituisce esattamente gli stessi risultati delle query precedenti senza eseguire l'analisi XML completa. La query presuppone alcuni presupposti sulla struttura di file XML, ad esempio l'elemento FilePath viene dopo FileHash e nessuno di essi ha attributi:

//even more efficient
SecurityEvent
| where EventID == 8002 //Only this event have FileHash
| where EventData !has "%SYSTEM32" //Early removal of unwanted records
| parse EventData with * "<FilePath>" FilePath "</FilePath>" * "<FileHash>" FileHash "</FileHash>" *
| summarize count() by FileHash, FilePath
| where FileHash != "" // No need to filter out %SYSTEM32 here as it was removed before

Dati usati per la query elaborata

Un fattore critico nell'elaborazione della query è il volume di dati analizzati e usati per l'elaborazione delle query. Azure Esplora dati usa ottimizzazioni aggressive che riducono notevolmente il volume di dati rispetto ad altre piattaforme dati. Esistono comunque fattori critici nella query che possono influire sul volume di dati usato.

Una query che elabora più di 2.000 KB di dati viene considerata una query che utilizza risorse eccessive. Una query che elabora più di 20.000 KB di dati viene considerata una query offensiva e potrebbe essere limitata.

Nei log di Monitoraggio di Azure la TimeGenerated colonna viene usata come modo per indicizzare i dati. La limitazione dei TimeGenerated valori a un intervallo più ristretto possibile migliorerà le prestazioni delle query. L'intervallo ristretto limita significativamente la quantità di dati da elaborare.

Evitare l'uso non necessario di operatori di ricerca e unione

Un altro fattore che aumenta i dati elaborati è l'uso di un numero elevato di tabelle. Questo scenario si verifica in genere quando search * vengono usati i comandi e union * . Questi comandi forzano il sistema a valutare ed analizzare i dati da tutte le tabelle nell'area di lavoro. In alcuni casi, potrebbero essere presenti centinaia di tabelle nell'area di lavoro. Provare a evitare di usare search * o qualsiasi ricerca senza definire l'ambito in una tabella specifica.

Ad esempio, le query seguenti producono esattamente lo stesso risultato, ma l'ultima è la più efficiente:

// This version scans all tables though only Perf has this kind of data
search "Processor Time" 
| summarize count(), avg(CounterValue)  by Computer
// This version scans all strings in Perf tables – much more efficient
Perf
| search "Processor Time" 
| summarize count(), avg(CounterValue)  by Computer
// This is the most efficient version 
Perf 
| where CounterName == "% Processor Time"  
| summarize count(), avg(CounterValue)  by Computer

Aggiungere filtri iniziali alla query

Un altro metodo per ridurre il volume di dati consiste nell'avere condizioni nelle prime fasi della query. La piattaforma azure Esplora dati include una cache che consente di sapere quali partizioni includono dati rilevanti per una condizione specificawhere. Ad esempio, se una query contiene where EventID == 4624, la query verrà distribuita solo ai nodi che gestiscono le partizioni con eventi corrispondenti.

Le query di esempio seguenti producono esattamente lo stesso risultato, ma la seconda è più efficiente:

//less efficient
SecurityEvent
| summarize LoginSessions = dcount(LogonGuid) by Account
//more efficient
SecurityEvent
| where EventID == 4624 //Logon GUID is relevant only for logon event
| summarize LoginSessions = dcount(LogonGuid) by Account

Evitare più analisi degli stessi dati di origine usando funzioni di aggregazione condizionale e la funzione di materializzazione

Quando una query include diverse sottoquery unite tramite operatori join o union, ogni sottoquery analizza l'intera origine separatamente. Unisce quindi i risultati. Questa azione moltiplica il numero di volte in cui i dati vengono analizzati, un fattore critico nei set di dati di grandi dimensioni.

Una tecnica per evitare questo scenario consiste nell'usare le funzioni di aggregazione condizionale. La maggior parte delle funzioni di aggregazione usate in un operatore di riepilogo ha una versione condizionale che è possibile usare per un singolo operatore summarize con più condizioni.

Ad esempio, le query seguenti mostrano il numero di eventi di accesso e il numero di eventi di esecuzione del processo per ogni account. Restituiscono gli stessi risultati, ma la prima query analizza i dati due volte. La seconda query esegue l'analisi una sola volta:

//Scans the SecurityEvent table twice and perform expensive join
SecurityEvent
| where EventID == 4624 //Login event
| summarize LoginCount = count() by Account
| join 
(
    SecurityEvent
    | where EventID == 4688 //Process execution event
    | summarize ExecutionCount = count(), ExecutedProcesses = make_set(Process) by Account
) on Account
//Scan only once with no join
SecurityEvent
| where EventID == 4624 or EventID == 4688 //early filter
| summarize LoginCount = countif(EventID == 4624), ExecutionCount = countif(EventID == 4688), ExecutedProcesses = make_set_if(Process,EventID == 4688)  by Account

Un altro caso in cui le sottoquery non sono necessarie è il filtro preliminare per un operatore di analisi per assicurarsi che elabora solo i record che corrispondono a un modello specifico. Non sono necessari perché l'operatore parse e altri operatori simili restituiscono risultati vuoti quando il criterio non corrisponde. Le due query seguenti restituiscono esattamente gli stessi risultati, ma la seconda query analizza i dati una sola volta. Nella seconda query ogni comando di analisi è rilevante solo per i relativi eventi. L'operatore extend mostra in seguito come fare riferimento a una situazione di dati vuota:

//Scan SecurityEvent table twice
union(
SecurityEvent
| where EventID == 8002 
| parse EventData with * "<FilePath>" FilePath "</FilePath>" * "<FileHash>" FileHash "</FileHash>" *
| distinct FilePath
),(
SecurityEvent
| where EventID == 4799
| parse EventData with * "CallerProcessName\">" CallerProcessName1 "</Data>" * 
| distinct CallerProcessName1
)
//Single scan of the SecurityEvent table
SecurityEvent
| where EventID == 8002 or EventID == 4799
| parse EventData with * "<FilePath>" FilePath "</FilePath>" * "<FileHash>" FileHash "</FileHash>" * //Relevant only for event 8002
| parse EventData with * "CallerProcessName\">" CallerProcessName1 "</Data>" *  //Relevant only for event 4799
| extend FilePath = iif(isempty(CallerProcessName1),FilePath,"")
| distinct FilePath, CallerProcessName1

Quando la query precedente non consente di evitare di usare sottoquery, un'altra tecnica consiste nell'suggerire al motore di query un'unica origine di dati usata in ognuna di esse usando la funzione materialize(). Questa tecnica è utile quando i dati di origine provengono da una funzione usata più volte all'interno della query. Materialize è efficace quando l'output della sottoquery è molto più piccolo dell'input. Il motore di query memorizza nella cache e riutilizza l'output in tutte le occorrenze.

Ridurre il numero di colonne recuperate

Poiché Azure Esplora dati è un archivio dati a colonne, il recupero di ogni colonna è indipendente dagli altri. Il numero di colonne recuperate direttamente influisce sul volume di dati complessivo. È consigliabile includere solo le colonne nell'output necessarie riepilogando i risultati o proiettando le colonne specifiche.

Azure Esplora dati offre diverse ottimizzazioni per ridurre il numero di colonne recuperate. Se determina che una colonna non è necessaria, ad esempio, se non viene fatto riferimento nel comando summarize , non la recupererà.

Ad esempio, la seconda query potrebbe elaborare tre volte più dati perché deve recuperare non una colonna ma tre:

//Less columns --> Less data
SecurityEvent
| summarize count() by Computer  
//More columns --> More data
SecurityEvent
| summarize count(), dcount(EventID), avg(Level) by Computer  

Intervallo di tempo della query elaborata

Tutti i log nei log di Monitoraggio di Azure vengono partizionati in base alla TimeGenerated colonna . Il numero di partizioni a cui si accede è direttamente correlato all'intervallo di tempo. La riduzione dell'intervallo di tempo è il modo più efficiente per garantire l'esecuzione di una query di richiesta.

Una query con un intervallo di tempo superiore a 15 giorni viene considerata una query che utilizza risorse eccessive. Una query con un intervallo di tempo di più di 90 giorni viene considerata una query offensiva e potrebbe essere limitata.

È possibile impostare l'intervallo di tempo usando il selettore dell'intervallo di tempo nella schermata Log Analytics, come descritto in Ambito query di log e intervallo di tempo in Log Analytics di Monitoraggio di Azure. Questo metodo è consigliato perché l'intervallo di tempo selezionato viene passato al back-end usando i metadati della query.

Un metodo alternativo consiste nell'includere in modo esplicito una condizione TimeGenerated where nella query. Usare questo metodo perché assicura che l'intervallo di tempo sia fisso, anche quando la query viene usata da un'interfaccia diversa.

Assicurarsi che tutte le parti della query dispongano TimeGenerated di filtri. Quando una query dispone di sottoquery che recuperano dati da varie tabelle o dalla stessa tabella, ogni query deve includere la propria condizione where .

Assicurarsi che tutte le sottoquery abbiano il filtro TimeGenerated

Nella query seguente, ad esempio, la Perf tabella verrà analizzata solo per l'ultimo giorno. La Heartbeat tabella verrà analizzata per tutta la sua storia, che potrebbe essere fino a due anni:

Perf
| where TimeGenerated > ago(1d)
| summarize avg(CounterValue) by Computer, CounterName
| join kind=leftouter (
    Heartbeat
    //No time span filter in this part of the query
    | summarize IPs = makeset(ComputerIP, 10) by  Computer
) on Computer

Un caso comune in cui si verifica un errore di questo tipo è quando viene usato arg_max() per trovare l'occorrenza più recente. Ad esempio:

Perf
| where TimeGenerated > ago(1d)
| summarize avg(CounterValue) by Computer, CounterName
| join kind=leftouter (
    Heartbeat
    //No time span filter in this part of the query
    | summarize arg_max(TimeGenerated, *), min(TimeGenerated)   
by Computer
) on Computer

È possibile correggere facilmente questa situazione aggiungendo un filtro temporale nella query interna:

Perf
| where TimeGenerated > ago(1d)
| summarize avg(CounterValue) by Computer, CounterName
| join kind=leftouter (
    Heartbeat
    | where TimeGenerated > ago(1d) //filter for this part
    | summarize arg_max(TimeGenerated, *), min(TimeGenerated)   
by Computer
) on Computer

Un altro esempio di questo errore è quando si esegue il filtro dell'ambito temporale subito dopo un'unione su più tabelle. Quando si esegue l'unione, ogni sottoquery deve essere con ambito. È possibile usare un'istruzione let per garantire la coerenza dell'ambito.

Ad esempio, la query seguente analizzerà tutti i dati nelle Heartbeat tabelle e Perf , non solo l'ultimo giorno:

Heartbeat 
| summarize arg_min(TimeGenerated,*) by Computer
| union (
    Perf 
    | summarize arg_min(TimeGenerated,*) by Computer) 
| where TimeGenerated > ago(1d)
| summarize min(TimeGenerated) by Computer

Per correggere la query:

let MinTime = ago(1d);
Heartbeat 
| where TimeGenerated > MinTime
| summarize arg_min(TimeGenerated,*) by Computer
| union (
    Perf 
    | where TimeGenerated > MinTime
    | summarize arg_min(TimeGenerated,*) by Computer) 
| summarize min(TimeGenerated) by Computer

Limitazioni di misurazione dell'intervallo di tempo

La misurazione è sempre maggiore del tempo effettivo specificato. Ad esempio, se il filtro sulla query è di 7 giorni, il sistema potrebbe analizzare 7,5 o 8,1 giorni. Questa varianza è dovuta al fatto che il sistema partiziona i dati in blocchi di dimensioni variabili. Per assicurarsi che tutti i record pertinenti vengano analizzati, il sistema analizza l'intera partizione. Questo processo potrebbe coprire diverse ore e anche più di un giorno.

Esistono diversi casi in cui il sistema non può fornire una misurazione accurata dell'intervallo di tempo. Questa situazione si verifica nella maggior parte dei casi in cui l'intervallo della query è inferiore a un giorno o in query su più aree di lavoro.

Importante

Questo indicatore presenta solo i dati elaborati nel cluster immediato. In una query in più aree rappresenta solo una delle aree. In una query su più aree di lavoro potrebbe non includere tutte le aree di lavoro.

Età dei dati elaborati

Azure Esplora dati usa diversi livelli di archiviazione: in memoria, dischi SSD locali e BLOB di Azure molto più lenti. Più recenti sono i dati, maggiore è la probabilità che vengano archiviati in un livello più efficiente con una latenza più piccola, riducendo così la durata della query e la CPU. Oltre ai dati stessi, il sistema dispone anche di una cache per i metadati. I dati meno recenti, minore è la probabilità che i metadati si troveranno in una cache.

Una query che elabora i dati di più di 14 giorni viene considerata una query che utilizza risorse eccessive.

Alcune query richiedono l'uso di dati obsoleti, ma esistono anche casi in cui i dati obsoleti vengono usati per errore. Questo scenario si verifica quando le query vengono eseguite senza fornire un intervallo di tempo nei relativi metadati e non tutti i riferimenti di tabella includono un filtro sulla TimeGenerated colonna. In questi casi, il sistema analizzerà tutti i dati archiviati nella tabella. Quando la conservazione dei dati è lunga, può coprire intervalli di tempo lunghi. Di conseguenza, i dati obsoleti come il periodo di conservazione dei dati vengono analizzati.

Tali casi possono essere, ad esempio:

  • Non impostando l'intervallo di tempo in Log Analytics con una sottoquery non limitata. Vedere l'esempio precedente.
  • Uso dell'API senza i parametri facoltativi dell'intervallo di tempo.
  • L'uso di un client che non forza un intervallo di tempo, ad esempio, come il connettore Power BI.

Vedere esempi e note nella sezione precedente perché sono rilevanti anche in questo caso.

Numero di aree

In alcune situazioni è possibile eseguire una singola query in aree diverse. Ad esempio:

  • Quando diverse aree di lavoro sono elencate in modo esplicito e si trovano in aree diverse.
  • Quando una query con ambito risorsa recupera i dati e i dati vengono archiviati in più aree di lavoro che si trovano in aree diverse.

L'esecuzione di query tra aree richiede al sistema di serializzare e trasferire nel back-end blocchi di dati intermedi di grandi dimensioni che in genere sono molto più grandi rispetto ai risultati finali della query. Limita inoltre la capacità del sistema di eseguire ottimizzazioni e euristica e usare le cache.

Se non esiste alcun motivo per analizzare tutte queste aree, modificare l'ambito in modo che includa meno aree. Se l'ambito della risorsa è ridotto a icona, ma molte aree vengono ancora usate, potrebbe verificarsi a causa di errori di configurazione. Ad esempio, i log di controllo e le impostazioni di diagnostica potrebbero essere inviati a aree di lavoro diverse in aree diverse o potrebbero essere presenti più configurazioni delle impostazioni di diagnostica.

Una query che si estende su più di tre aree viene considerata una query che utilizza risorse eccessive. Una query che si estende su più di sei aree è considerata una query non offensiva e potrebbe essere limitata.

Importante

Quando una query viene eseguita in più aree, le misurazioni della CPU e dei dati non saranno accurate e rappresenteranno la misurazione di una sola delle aree.

Numero di aree di lavoro

Le aree di lavoro sono contenitori logici usati per separare e amministrare i dati dei log. Il back-end ottimizza i posizionamento delle aree di lavoro nei cluster fisici all'interno dell'area selezionata.

L'uso di più aree di lavoro può derivare da istanze quando:

  • Sono elencate in modo esplicito diverse aree di lavoro.
  • Una query con ambito risorsa recupera i dati e i dati vengono archiviati in più aree di lavoro.

L'esecuzione tra più aree e tra cluster di query richiede al sistema di serializzare e trasferire nel back-end blocchi di dati intermedi di grandi dimensioni che in genere sono molto più grandi dei risultati finali della query. Limita inoltre la capacità del sistema di eseguire ottimizzazioni e euristica e usare le cache.

Una query che si estende su più di cinque aree di lavoro viene considerata una query che utilizza risorse eccessive. Le query non possono estendersi su più di 100 aree di lavoro.

Importante

  • In alcuni scenari con più aree di lavoro, le misurazioni della CPU e dei dati non saranno accurate e rappresenteranno la misurazione solo di alcune aree di lavoro.
  • Le query tra aree di lavoro hanno un identificatore esplicito: ID area di lavoro o ID risorsa dell'area di lavoro di Azure, consumano meno risorse e sono più efficienti.

Parallelism

I log di Monitoraggio di Azure usano cluster di grandi dimensioni di Azure Esplora dati per eseguire query. Questi cluster variano in scala e possono arrivare fino a decine di nodi di calcolo. Il sistema ridimensiona automaticamente i cluster in base alla logica e alla capacità di posizionamento dell'area di lavoro.

Per eseguire in modo efficiente una query, viene partizionata e distribuita nei nodi di calcolo in base ai dati necessari per l'elaborazione. In alcune situazioni, il sistema non può eseguire questo passaggio in modo efficiente, che può portare a una lunga durata della query.

I comportamenti delle query che possono ridurre il parallelismo includono:

  • Uso di funzioni di serializzazione e finestra, ad esempio l'operatore serialize, next(), prev() e le funzioni di riga. In alcuni di questi casi è possibile usare le funzioni di analisi delle serie temporali e dell'analisi degli utenti. La serializzazione inefficiente può verificarsi anche se gli operatori seguenti non vengono usati alla fine della query: range, sort, order, top, top-hitter e getschema.
  • L'uso della funzione di aggregazione dcount() impone al sistema di disporre di una copia centrale dei valori distinti. Quando la scala dei dati è elevata, è consigliabile usare i parametri facoltativi della funzione per ridurre l'accuratezza dcount .
  • In molti casi, l'operatore join riduce il parallelismo complessivo. Esaminare shuffle join come alternativa quando le prestazioni sono problematiche.
  • Nelle query con ambito di risorse, i controlli di controllo degli accessi in base al ruolo di Kubernetes o controllo degli accessi in base al ruolo di Azure potrebbero rimanere in situazioni in cui è presente un numero elevato di assegnazioni di ruolo di Azure. Questa situazione potrebbe portare a controlli più lunghi che comportano un parallelismo inferiore. Ad esempio, una query potrebbe essere eseguita in una sottoscrizione in cui sono presenti migliaia di risorse e ogni risorsa ha molte assegnazioni di ruolo a livello di risorsa, non nella sottoscrizione o nel gruppo di risorse.
  • Se una query elabora piccoli blocchi di dati, il parallelismo sarà basso perché il sistema non lo distribuirà in molti nodi di calcolo.

Passaggi successivi

Documentazione di riferimento per il Linguaggio di query Kusto