Optimización de las consultas de registro en Azure Monitor

Los registros de Azure Monitor usan Azure Data Explorer para almacenar los datos de registro y ejecutar consultas para analizar los datos. Crea, administra y mantiene los clústeres de Azure Data Explorer automáticamente y los optimiza para la carga de trabajo de análisis de registros. Al ejecutar una consulta, se optimiza y se redirige al clúster de Azure Data Explorer adecuado que almacena los datos del área de trabajo.

Los registros de Azure Monitor y Azure Data Explorer usan muchos mecanismos de optimización de consultas automática. Las optimizaciones automáticas proporcionan un aumento significativo, pero en algunos casos se puede mejorar considerablemente el rendimiento de las consultas. En este artículo se explican las consideraciones de rendimiento y varias técnicas para corregirlas.

La mayoría de las técnicas son comunes a las consultas que se ejecutan directamente en Azure Data Explorer y registros de Azure Monitor. Aquí también se describen varias consideraciones únicas de registros de Azure Monitor. Para obtener más información sobre las sugerencias de optimización de Azure Data Explorer, consulte Procedimientos recomendados sobre las consultas.

Las consultas optimizadas:

  • Se ejecutarán más rápido y reducirán la duración total de la ejecución de la consulta.
  • Tendrán menos posibilidades de que se limiten o rechacen.

Preste especial atención a las consultas que se usan para el uso recurrente y simultáneo, como paneles, alertas, Azure Logic Apps y Power BI. El impacto de una consulta ineficaz en estos casos es considerable.

Este es un tutorial en vídeo detallado sobre la optimización de consultas.

Panel Detalles de la consulta

Después de ejecutar una consulta en Log Analytics, seleccione Detalles de la consulta en la esquina inferior derecha de la pantalla para abrir el panel Detalles de la consulta. En este panel se muestran los resultados de varios indicadores de rendimiento para la consulta. Estos indicadores de rendimiento se describen en la sección siguiente.

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

Indicadores de rendimiento de consultas

Los siguientes indicadores de rendimiento de consultas están disponibles para todas las consultas que se ejecutan:

  • CPU total: Proceso general usado para procesar la consulta en todos los nodos de proceso. Representa el tiempo que se usa para la computación, el análisis y la captura de datos.
  • Datos usados para la consulta procesada: Datos globales a los que se obtuvo acceso para procesar la consulta. Se ve afectado por el tamaño de la tabla de destino, el intervalo de tiempo usado, los filtros aplicados y el número de columnas a que se hace referencia.
  • Intervalo de tiempo de la consulta procesada: La diferencia entre los datos más recientes y los más antiguos a los que se obtuvo acceso para procesar la consulta. Se ve afectado por el intervalo de tiempo explícito especificado para la consulta.
  • Antigüedad de los datos procesados: La diferencia entre los datos actuales y los más antiguos a los que se obtuvo acceso para procesar la consulta. Afecta enormemente a la eficacia de la captura de datos.
  • Número de áreas de trabajo: número de áreas de trabajo a las que se accedió durante el procesamiento de la consulta en función de una selección implícita o explícita.
  • Número de regiones: número de regiones a las que se accedió durante el procesamiento de la consulta en función de una selección implícita o explícita de áreas de trabajo. Las consultas de varias regiones son mucho menos eficientes y los indicadores de rendimiento presentan una cobertura parcial.
  • Paralelismo: Indica la cantidad de tiempo que el sistema pudo ejecutar esta consulta en varios nodos. Solo es relevante para las consultas que tienen un uso elevado de la CPU. Se ve afectado por el uso de funciones y operadores específicos.

CPU total

La CPU de cálculo real que se ha invertido para procesar esta consulta en todos los nodos de procesamiento de consultas. Como la mayoría de las consultas se ejecutan en un gran número de nodos, normalmente el total será mucho mayor que la duración de la ejecución de la consulta.

Si una consulta consume más de 100 segundos de CPU, se considera que consume demasiados recursos. Si una consulta consume más de 1000 segundos de CPU, se considera abusiva y podría verse limitada.

El tiempo de procesamiento de consultas se emplea en:

  • Recuperación de datos: la recuperación de datos antiguos consumirá más tiempo que la recuperación de datos recientes.
  • Procesamiento de datos: lógica y evaluación de los datos.

Además del tiempo invertido en los nodos de procesamiento de consultas, los registros de Azure Monitor dedican tiempo a:

  • Autenticar al usuario y comprobar que tiene permiso para acceder a estos datos.
  • Localizar el almacén de datos.
  • Analizar la consulta.
  • Asignar los nodos de procesamiento de consultas.

Este tiempo no se incluye en el tiempo de CPU total de la consulta.

Filtrado temprano de registros antes de usar funciones de CPU elevadas

Algunos de los comandos de consulta y las funciones realizan un gran consumo de CPU. Esto es especialmente cierto para los comandos que analizan JSON y XML o extraen expresiones regulares complejas. Este análisis puede producirse explícitamente a través de las funciones parse_json() o parse_xml() o implícitamente cuando se hace referencia a columnas dinámicas.

Estas funciones consumen CPU en proporción al número de filas que procesan. La optimización más eficaz consiste en agregar condiciones where al principio de la consulta. De este modo, pueden filtrar tantos registros como sea posible antes de que se ejecute la función que consume mucha CPU.

Por ejemplo, las siguientes consultas producen exactamente el mismo resultado, pero la segunda es la más eficaz, ya que la condición where antes del análisis excluye muchos registros:

//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

Evitar el uso de cláusulas where evaluadas

Las consultas que contienen cláusulas where en una columna evaluada en lugar de en columnas que están físicamente presentes en el conjunto de datos pierden eficacia. El filtrado de columnas evaluadas evita algunas optimizaciones del sistema cuando se administran grandes conjuntos de datos.

Por ejemplo, las siguientes consultas producen exactamente el mismo resultado, pero la segunda es más eficaz porque la condición where hace referencia a una columna integrada:

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

En algunos casos, la columna evaluada se crea implícitamente mediante el motor de procesamiento de consultas, ya que el filtrado no solo se realiza en el campo:

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

Uso de dimensiones y comandos de agregación efectivos para resúmenes y uniones

Algunos comandos de agregación como max(), sum(), count() y avg() tienen un impacto bajo en la CPU debido a su lógica. Otros son más complejos e incluyen heurística y estimaciones que les permiten ejecutarse de forma eficaz. Por ejemplo, dcount() usa el algoritmo HyperLogLog para proporcionar una estimación próxima para distinguir el recuento de grandes conjuntos de datos sin contar realmente cada valor.

Las funciones de percentil realizan aproximaciones similares mediante el algoritmo de percentil de clasificación más próximo. Algunos de los comandos incluyen parámetros opcionales para reducir su impacto. Por ejemplo, la función makeset() tiene un parámetro opcional para definir el tamaño máximo del conjunto, lo que afecta significativamente a la CPU y la memoria.

Los comandos join y summarize podrían provocar un uso intensivo de la CPU cuando procesan un gran conjunto de datos. Su complejidad está directamente relacionada con el número de valores posibles (denominado cardinalidad) de las columnas que usan, como by en summarize o como los atributos join. Para obtener una explicación y una optimización de join y summarize, consulte sus artículos de documentación y sugerencias de optimización.

Por ejemplo, las siguientes consultas producen exactamente el mismo resultado, porque CounterPath siempre tiene una asignación uno a uno para CounterName y ObjectName. La segunda es más eficaz, ya que la dimensión de agregación es más pequeña:

//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

El consumo de CPU también puede verse afectado por condiciones where o columnas extendidas que necesitan una computación intensiva. Todas las comparaciones triviales de cadenas, como equal == y startswith, tienen prácticamente el mismo impacto en la CPU. Las coincidencias de texto avanzadas tienen más impacto. En concreto, el operador has es más eficaz que el operador contains. Debido a las técnicas de control de cadenas, es más eficaz buscar cadenas con más de cuatro caracteres que cadenas cortas.

Por ejemplo, las siguientes consultas generan resultados similares en función de la directiva de nomenclatura Computer, pero la segunda es más eficaz:

//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

Este indicador solo presenta la CPU del clúster inmediato. En una consulta de varias regiones, solo representaría una de las regiones. En una consulta de varias áreas de trabajo, es posible que no incluya todas las áreas de trabajo.

Evite el análisis XML y JSON completo cuando funcione el análisis de cadenas

El análisis completo de un objeto XML o JSON puede consumir una gran cantidad de recursos de CPU y memoria. En muchos casos, cuando solo se necesitan uno o dos parámetros y los objetos XML o JSON son simples, es más fácil analizarlos como cadenas. Use el operador parse u otras técnicas de análisis de texto. La mejora del rendimiento será más significativa a medida que aumente el número de registros en el objeto XML o JSON. Es fundamental cuando el número de registros alcanza decenas de millones.

Por ejemplo, la consulta siguiente devuelve exactamente los mismos resultados que las consultas anteriores sin realizar un análisis XML completo. La consulta hace algunas suposiciones sobre la estructura del archivo XML, por ejemplo, que el elemento FilePath aparece después de FileHash y que ninguno de ellos tiene atributos:

//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

Datos usados para la consulta procesada

Un factor crítico en el procesamiento de la consulta es el volumen de datos que se examina y usa para el procesamiento de la consulta. Azure Data Explorer usa optimizaciones agresivas que reducen en gran medida el volumen de datos en comparación con otras plataformas de datos. Aun así, hay factores críticos en la consulta que pueden afectar al volumen de datos que se usa.

Si una consulta procesa más de 2000 KB de datos, se considera que consume demasiados recursos. Si una consulta procesa más de 20 000 KB de datos, se considera abusiva y podría verse limitada.

En los registros de Azure Monitor, la columna TimeGenerated se usa para indexar los datos. Si los valores de TimeGenerated se restringen tanto como sea posible, se producirá una mejora en el rendimiento de la consulta. Un intervalo reducido limita considerable la cantidad de datos que se tienen que procesar.

Evitar el uso innecesario de los operadores search y union

Otro factor que aumenta los datos que se procesan es el uso de un gran número de tablas. Esto suele ocurrir cuando se usan los comandos search * y union *. Estos comandos obligan al sistema a evaluar y digitalizar los datos de todas las tablas del área de trabajo. En algunos casos, puede haber cientos de tablas en el área de trabajo. Intente evitar el uso de search * o cualquier búsqueda sin definir su ámbito a una tabla específica.

Por ejemplo, las siguientes consultas producen exactamente el mismo resultado, pero la última es la más eficaz:

// 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

Adición de filtros iniciales a la consulta

Otro método para reducir el volumen de datos es tener condiciones where rápidamente en la consulta. La plataforma de Azure Data Explorer incluye una memoria caché que le permite saber qué particiones incluyen datos pertinentes para una condición where específica. Por ejemplo, si un consulta contiene where EventID == 4624, distribuirá la consulta solo en los nodos que controlan particiones con eventos coincidentes.

Las siguientes consultas de ejemplo producen exactamente el mismo resultado, pero la segunda es más eficaz:

//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

Cómo evitar varios exámenes de los mismos datos de origen mediante funciones de agregación condicional y la función materialize

Cuando una consulta tiene varias subconsultas que se combinan mediante operadores join o union, cada subconsulta examina todo el origen por separado y, luego, combina los resultados. Esta acción multiplica el número de veces que se examinan los datos, lo que es un factor crítico en conjuntos de datos grandes.

Una técnica para evitar esta situación es usar las funciones de agregación condicional. La mayoría de las funciones de agregación que se usan en el operador de resumen tienen una versión condicionada que se puede usar para un único operador de resumen con varias condiciones.

Por ejemplo, las siguientes consultas muestran el número de eventos de inicio de sesión y el número de eventos de ejecución de proceso de cada cuenta. Devuelven los mismos resultados, pero la primera consulta examina los datos dos veces. La segunda consulta los examina una sola vez:

//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

Otro caso en el que las subconsultas no son necesarias es el prefiltro del operador parse para asegurarse de que solo se procesan los registros que coinciden con un patrón específico. No son necesarias porque el operador parse y otros operadores similares devuelven resultados vacíos cuando el patrón no coincide. Las dos consultas siguientes devuelven exactamente los mismos resultados, pero la segunda consulta examina los datos una sola vez. En la segunda consulta, cada comando Parse solo es importante para sus eventos. Después, el operador extend muestra cómo hacer referencia a una situación de datos vacíos:

//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

Cuando la consulta anterior no permite evitar el uso de subconsultas, otra técnica es sugerir al motor de consultas que hay un único origen de datos que se usa en cada una de ellas mediante la función materialize(). Esta técnica resulta útil cuando los datos de origen proceden de una función que se usa varias veces dentro de la consulta. La función Materialize es eficaz cuando la salida de la subconsulta es mucho menor que la entrada. El motor de consultas almacenará en caché la salida y la reutilizará en todas las repeticiones.

Reducción del número de columnas que se recuperan

Dado que Azure Data Explorer es un almacén de datos en columnas, la recuperación de cada columna es independiente de las demás. El número de columnas que se recuperan influye directamente en el volumen de datos general. Solo se deben incluir las columnas de la salida que se necesitan para resumir los resultados o proyectar las columnas específicas.

Azure Data Explorer tiene varias optimizaciones para reducir el número de columnas recuperadas. Si se determina que una columna no es necesaria (por ejemplo, si el comando summarize no hace referencia a ella), no se recuperará.

Por ejemplo, la segunda consulta puede procesar tres veces más datos, ya que necesita capturar no una columna, sino tres:

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

Intervalo de tiempo de la consulta procesada

Todos los registros de Azure Monitor se dividen en particiones según la columna TimeGenerated. El número de particiones a las que se obtiene acceso está directamente relacionado con el intervalo de tiempo. La forma más eficaz de garantizar la ejecución de una consulta del símbolo del sistema consiste en reducir el intervalo de tiempo.

Si una consulta tiene un intervalo de tiempo superior a 15 días, se considera que consume demasiados recursos. Si una consulta tiene un intervalo de tiempo superior a 90 días, se considera abusiva y podría verse limitada.

Puede establecer el intervalo de tiempo con el selector de intervalo de tiempo en la pantalla de Log Analytics, tal como se describe en Ámbito e intervalo de tiempo de una consulta de registro en Log Analytics de Azure Monitor. Este es el método recomendado, ya que el intervalo de tiempo seleccionado se pasa al back-end mediante los metadatos de la consulta.

Un método alternativo consiste en incluir explícitamente una condición where en TimeGenerated en la consulta. Use este método, ya que garantiza que el intervalo de tiempo sea fijo, aunque la consulta se use desde una interfaz diferente.

Asegúrese de que todas las partes de la consulta tengan filtros TimeGenerated. Cuando una consulta tiene subconsultas que capturan datos de diferentes tablas o de la misma, cada consulta tiene que incluir su propia condición where.

Asegúrese de que todas las subconsultas tienen el filtro TimeGenerated

Por ejemplo, en la consulta siguiente, la tabla Perf solo se examinará para el último día. La tabla Heartbeat se examinará para la totalidad de su historial, que puede ser de hasta dos años:

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 común en el que se produce dicho error es cuando arg_max() se usa para buscar la repetición más reciente. Por ejemplo:

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

Esta situación se puede corregir fácilmente si se agrega un filtro de tiempo en la consulta 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

Otro ejemplo de este error es cuando se realiza el filtrado del ámbito de tiempo justo después de una unión en varias tablas. Al realizar la unión, se debe definir el ámbito de cada subconsulta. Puede usar una instrucción let para garantizar la coherencia del ámbito.

Por ejemplo, la siguiente consulta examinará todos los datos de las tablas Heartbeat y Perf, no solo del último día:

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

Para corregir la consulta:

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

Limitaciones de la medición de intervalos de tiempo

La medida siempre es mayor que el tiempo real especificado. Por ejemplo, si el filtro de la consulta es 7 días, el sistema podría examinar 7,5 o 8,1 días. Esta varianza se debe a que el sistema crea particiones de los datos en fragmentos de distintos tamaños. Para tener la certeza de que se analizan todos los registros pertinentes, el sistema examina toda la partición. Este proceso puede tardar varias horas, e incluso más de un día.

Hay varios casos en los que el sistema no puede proporcionar una medida precisa del intervalo de tiempo. Esta situación se produce en la mayoría de los casos en los que el intervalo de la consulta es inferior a un día o en consultas de varias áreas de trabajo.

Importante

Este indicador solo presenta los datos procesados del clúster inmediato. En una consulta de varias regiones, solo representaría una de las regiones. En una consulta de varias áreas de trabajo, es posible que no incluya todas las áreas de trabajo.

Antigüedad de los datos procesados

Azure Data Explorer usa varias capas de almacenamiento: en memoria, discos SSD locales y blobs de Azure mucho más lentos. Cuanto más recientes sean los datos, más alta será la posibilidad de que se almacenen en una capa más eficiente y con menor latencia, lo que reduce el uso de la CPU y la duración de la consulta. Al margen de los propios datos, el sistema también tiene una memoria caché para los metadatos. Cuanto más antiguos sean los datos, menor será la probabilidad de que sus metadatos estén en una caché.

Se considera que una consulta que procese datos con más de 14 días de antigüedad consume demasiados recursos.

Algunas consultas requieren el uso de datos antiguos, pero también hay casos en los que dichos datos se usan por error. Esto sucede cuando las consultas se ejecutan sin proporcionar un intervalo de tiempo en sus metadatos y no todas las referencias de tabla incluyen un filtro en la columna TimeGenerated. En estos casos, el sistema examinará todos los datos que estén almacenados en la tabla. Cuando la retención de datos es larga, puede abarcar intervalos de tiempo largos. Como resultado, se examinan datos que son tan antiguos como el período de retención de datos.

A continuación, se indican algunos ejemplos de dichos casos:

  • No establecer el intervalo de tiempo en Log Analytics con una subconsulta que no esté limitada. Consulte el ejemplo anterior.
  • Usar la API sin los parámetros opcionales del intervalo de tiempo.
  • Usar un cliente que no fuerce un intervalo de tiempo, como el conector de Power BI.

Consulte los ejemplos y las notas de la sección anterior, ya que también son pertinentes en este caso.

Número de regiones

En algunos casos, una única consulta podría ejecutarse en diferentes regiones. Por ejemplo:

  • Cuando se enumeran explícitamente varias áreas de trabajo y se encuentran en diferentes regiones.
  • Cuando una consulta con ámbito de recurso está capturando los datos y estos se almacenan en varias áreas de trabajo ubicadas en diferentes regiones.

La ejecución de consultas en varias regiones requiere que el sistema efectúe la serialización y la transferencia en los fragmentos grandes del back-end de los datos intermedios que suelen ser mucho mayores que los resultados finales de la consulta. También limita la capacidad del sistema de llevar a cabo optimizaciones, heurística y usar cachés.

Si no hay motivo alguno para examinar todas estas regiones, ajuste el ámbito para que cubra menos regiones. Si el ámbito del recurso se minimiza, pero aún se usan varias regiones, puede deberse a un error de configuración. Por ejemplo, la configuración de diagnóstico y los registros de auditoría podría enviarse a diferentes áreas de trabajo en distintas regiones o podría haber varias configuraciones de diagnóstico.

Si una consulta abarca más de tres regiones, se considera que consume demasiados recursos. Si una consulta abarca más de seis regiones, se considera abusiva y podría verse limitada.

Importante

Cuando una consulta se ejecuta en varias regiones, las medidas de los datos y la CPU no serán precisas y solo representarán la medida de una de las regiones.

Número de áreas de trabajo

Las áreas de trabajo son contenedores lógicos que se usan para separar y administrar los datos de registros. El back-end optimiza las selecciones de ubicación de las áreas de trabajo en clústeres físicos dentro de la región seleccionada.

El uso de varias áreas de trabajo puede deberse a alguno de los siguientes casos:

  • Cuando se enumeran explícitamente varias áreas de trabajo.
  • Cuando una consulta con ámbito de recurso está capturando los datos y estos se almacenan en varias áreas de trabajo.

La ejecución de consultas en varios clústeres y varias regiones requiere que el sistema efectúe la serialización y la transferencia en los fragmentos grandes del back-end de los datos intermedios que suelen ser mucho mayores que los resultados finales de la consulta. También limita la capacidad del sistema de llevar a cabo optimizaciones, heurística y usar cachés.

Si una consulta abarca más de cinco áreas de trabajo, se considera que consume demasiados recursos. Las consultas no pueden abarcar más de 100 áreas de trabajo.

Importante

  • En algunos escenarios de varias áreas de trabajo, las medidas de los datos y la CPU no serán precisas y solo representarán la medida de algunas de las áreas de trabajo.
  • Las consultas entre espacios de trabajo que tienen un identificador explícito, como el id. del área de trabajo o el id. del área de trabajo de Azure Resource Manager, consumen menos recursos y tienen un mayor rendimiento.

Paralelismo

Los registros de Azure Monitor usan clústeres grandes de Azure Data Explorer para ejecutar consultas. Estos clústeres varían en escala y pueden llegar a abarcar decenas de nodos de proceso. El sistema escala automáticamente los clústeres en función de la capacidad y la lógica de selección de ubicación del área de trabajo.

Para ejecutar una consulta de forma eficaz, se divide en particiones y se distribuye a los nodos de ejecución en función de los datos necesarios para su procesamiento. En algunas situaciones, el sistema no puede realizar este paso de forma eficaz, lo que puede provocar una larga duración de la consulta.

Entre los comportamientos de las consultas que pueden reducir el paralelismo se incluyen los siguientes:

  • Uso de las funciones de ventana y serialización, como el operador serialize, next(), prev() y las funciones row. Las funciones de análisis de usuario y serie temporal pueden usarse en algunos de estos casos. También podría producirse una serialización ineficaz si los siguientes operadores no se usan al final de la consulta: range, sort, order, top, top-hitters y getschema.
  • El uso de la función de agregación dcount() obliga al sistema a tener una copia central de los distintos valores. Cuando la escala de datos es alta, considere la posibilidad de usar los parámetros opcionales de la función dcount para reducir la precisión.
  • En muchos casos, el operador join reduce el paralelismo general. Considere shuffle join como alternativa cuando el rendimiento sea problemático.
  • En las consultas cuyo ámbito son los recursos, las comprobaciones de control de acceso basado en roles (RBAC) de Kubernetes o Azure RBAC previas a la ejecución podrían demorarse en aquellos casos en los que hay muchas asignaciones de roles de Azure. Esta situación puede provocar comprobaciones más largas, lo que generaría un paralelismo más bajo. Por ejemplo, una consulta podría ejecutarse en una suscripción en la que hay miles de recursos y cada recurso tiene varias asignaciones de roles en el nivel de recurso, no en la suscripción ni en el grupo de recursos.
  • Si una consulta procesa fragmentos de datos pequeños, su paralelismo será bajo, ya que el sistema no la propagará en muchos nodos de ejecución.

Pasos siguientes

Documentación de referencia del Lenguaje de consulta Kusto