Compartir a través de


Optimizar el rendimiento utilizando QueryExpression

Este artículo describe formas de optimizar el rendimiento al recuperar datos mediante QueryExpression.

Patrones a evitar

Redactar consultas optimizadas para Dataverse es vital para garantizar que las aplicaciones ofrezcan una experiencia rápida, receptiva y fiable. Esta sección describe los patrones que se deben evitar y los conceptos que se deben comprender al redactar consultas para tablas estándar utilizando el mensaje RetrieveMultiple, o mensajes que tienen un parámetro que hereda de la clase QueryBase. Esta guía también se aplica cuando se envía una solicitud a una colección de registros mediante OData. GET Es posible que las instrucciones aquí no se apliquen a tablas elásticas o cuando se utiliza la búsqueda de Dataverse.

Minimice el número de columnas seleccionadas

No incluya columnas que no necesite en su consulta. Las consultas que devuelven todas las columnas o incluyen una gran cantidad de columnas pueden encontrar problemas de rendimiento debido al tamaño de conjunto de datos o la complejidad de la consulta.

Esta práctica es especialmente cierta para columnas lógicas. Una columna lógica contiene valores que se almacenan en diferentes tablas de bases de datos. La propiedad AttributeMetadata.IsLogical le indica si una columna es una columna lógica. Las consultas que contienen muchas columnas lógicas son más lentas porque Dataverse necesita combinar los datos de otras tablas de bases de datos.

Evite los comodines iniciales en condiciones de filtro

Las consultas que utilizan condiciones con comodines iniciales (ya sea explícita o implícitamente con un operador como ends-with) pueden provocar un mal rendimiento. Dataverse no puede aprovechar los índices de la base de datos cuando una consulta utiliza comodines iniciales, lo que obliga a SQL a escanear toda la tabla. Los escaneos de tablas pueden ocurrir incluso si hay otras consultas con comodines no principales que limitan el conjunto de resultados.

El siguiente ejemplo es un elemento de condición FetchXml que utiliza un comodín inicial:

<condition attribute='accountnumber'
   operator='like'
   value='%234' />

El siguiente ejemplo es una QueryExpression ConditionExpression que utiliza un comodín inicial:

new ConditionExpression("accountnumber", ConditionOperator.Like, "%234")

El siguiente ejemplo es una consulta OData que utiliza un comodín inicial tarjeta:

$filter=startswith(accountnumber,'%234')

Cuando se agota el tiempo de espera de las consultas y se detecta este patrón, Dataverse devuelve un error único para ayudar a identificar qué consultas utilizan este patrón:

Nombre: LeadingWildcardCauseTimeout
Código: 0x80048573
Número: -2147187341
Mensaje: The database operation timed out; this may be due to a leading wildcard value being used in a filter condition. Please consider removing filter conditions on leading wildcard values, as these filter conditions are expensive and may cause timeouts.

Dataverse limita fuertemente las consultas con comodines que se identifican como un riesgo para la salud de la organización para ayudar a prevenir interrupciones. Más información sobre limitación de consulta

Si utiliza consultas con comodines principales, investigue estas opciones:

  • Use en su lugar la búsqueda de Dataverse.
  • Cambie su modelo de datos para ayudar a las personas a evitar la necesidad de comodines principales.

Obtenga más información sobre el uso de caracteres comodín en condiciones para valores de cadena

Evite el uso de fórmulas o columnas calculadas en condiciones de filtro

Los valores de fórmula y columnas calculadas se calculan en tiempo real cuando se recuperan. Las consultas que utilizan filtros en estas columnas obligan a Dataverse a calcular el valor de cada registro posible que se puede devolver para que se pueda aplicar el filtro. Las consultas son más lentas porque Dataverse no se puede mejorar el rendimiento de estas consultas usando SQL.

Cuando se agota el tiempo de espera de las consultas y se detecta este patrón, Dataverse devuelve un error único para ayudar a identificar qué consultas utilizan este patrón:

Nombre: ComputedColumnCauseTimeout
Código: 0x80048574
Número: -2147187340
Mensaje: The database operation timed out; this may be due to a computed column being used in a filter condition. Please consider removing filter conditions on computed columns, as these filter conditions are expensive and may cause timeouts.

Para ayudar a evitar interrupciones, Dataverse aplica limitaciones en las consultas que tienen filtros en columnas calculadas que se identifican como un riesgo para la salud del entorno. Más información sobre limitación de consulta

Evite ordenar por columnas de elección

Al utilizar FetchXml o QueryExpression, al ordenar los resultados de la consulta utilizando una columna de opción, los resultados se ordenan utilizando la etiqueta localizada para cada opción de opción. Ordenar por el valor numérico almacenado en la base de datos no proporcionaría una buena experiencia en su aplicación. Debe saber que ordenar columnas de elección requiere más recursos informáticos para unir y ordenar las filas por el valor de etiqueta localizado. Este trabajo adicional hace que la consulta sea más lenta. Si es posible, intente evitar ordenar los resultados por valores de columna de elección.

Nota

OData es diferente. Con la Dataverse API web, $orderby ordena las filas utilizando el valor entero de la columna de elección en lugar de la etiqueta localizada.

Ordenar por columnas en tablas relacionadas hace que la consulta sea más lenta debido a la complejidad adicional.

El pedido por tablas relacionadas solo debe realizarse cuando sea necesario, como se describe aquí:

Evite el uso de condiciones en columnas de texto grandes

Dataverse tiene dos tipos de columnas que pueden almacenar grandes cadenas de texto:

El límite para ambas columnas se especifica mediante la propiedad MaxLength.

Puede utilizar condiciones en columnas de cadena que tengan un MaxLength configurado para menos de 850 caracteres.

Todas las columnas de notas o columnas de cadena con un MaxLength mayor que 850 se definen en Dataverse como columnas de texto grandes. Las columnas de texto grandes son demasiado grandes para indexarlas de manera efectiva, lo que genera un mal rendimiento cuando se incluyen en una condición de filtro.

Dataverse La búsqueda es una mejor opción para consultar datos en este tipo de columnas.

Sugerencias de consulta

Importante

Aplique estas opciones únicamente cuando lo recomiende el soporte técnico de Microsoft. El uso incorrecto de estas opciones puede dañar el rendimiento de una consulta.

Microsoft SQL Server admite muchas sugerencias de consulta para optimizar las consultas. QueryExpression admite sugerencias de consulta y puede pasar estas opciones de consulta a SQL Server usando la propiedad QueryExpression.QueryHints.

Opción de consulta Sugerencia de SQL Server
ForceOrder Forzar orden
DisableRowGoal Sugerencia: DISABLE_OPTIMIZER_ROWGOAL
EnableOptimizerHotfixes Sugerencia: ENABLE_QUERY_OPTIMIZER_HOTFIXES
LoopJoin Combinación de bucle
MergeJoin Combinación de mezcla
HashJoin Combinación hash
NO_PERFORMANCE_SPOOL NO_PERFORMANCE_SPOOL
ENABLE_HIST_AMENDMENT_FOR_ASC_KEYS Sugerencia: ENABLE_HIST_AMENDMENT_FOR_ASC_KEYS

Más información: Sugerencias (Transact-SQL) - Consulta

No lock

En versiones anteriores, la propiedad QueryExpression.NoLock se usaba para evitar bloqueos compartidos en registros. Ya no es necesario incluir esta propiedad

Sugerencia de combinación

Puede mejorar el rendimiento al agregar un FilterExpression que establece el ConditionExpression para columnas en diferentes tablas configurando la propiedad FilterExpression.FilterHint en union. Pero existen algunas restricciones:

  • FilterExpression.FilterOperator debe usar LogicalOperator.Or.
  • Cada consulta puede contener sólo una sugerencia de union.
  • Si una FilterExpression con sugerencia de union no está en el filtro de nivel superior, Dataverse transforma la consulta y mueve el filtro con una sugerencia de union al filtro raíz.
  • Si la sugerencia de union tiene más de tres niveles de profundidad, se ignora.

El siguiente ejemplo establece un filtro con la sugerencia de union en la columna telephone1 para las tablas cuenta y contacto.

QueryExpression query = new("email")
{
   ColumnSet = new ColumnSet("activityid", "subject"),
   Criteria = new FilterExpression(LogicalOperator.And)
   {
      Conditions = {
         {
            new ConditionExpression(
               attributeName:"subject",
               conditionOperator:ConditionOperator.Like,
               value: "Alert:%")
         },
         {
            new ConditionExpression(
               attributeName:"statecode",
               conditionOperator:ConditionOperator.Equal,
               value: 0)
         }
      },
      Filters = {
         {
            new FilterExpression(LogicalOperator.Or){
               FilterHint = "union",
               Conditions = {
                  {
                     new ConditionExpression(
                        attributeName:"telephone1",
                        conditionOperator:ConditionOperator.Equal,
                        value: "555-123-4567"){
                           EntityName = "ac"
                        }
                  },
                  {
                     new ConditionExpression(
                        attributeName:"telephone1",
                        conditionOperator:ConditionOperator.Equal,
                        value: "555-123-4567"){
                           EntityName = "co"
                        }
                  }
               }
            }
         }
      }
   }
};        

LinkEntity linkToAccount = query.AddLink(
      linkToEntityName: "account",
      linkFromAttributeName: "regardingobjectid",
      linkToAttributeName: "accountid",
      joinOperator: JoinOperator.LeftOuter);
linkToAccount.EntityAlias = "ac";

LinkEntity linkToContact = query.AddLink(
      linkToEntityName: "contact",
      linkFromAttributeName: "regardingobjectid",
      linkToAttributeName: "contactid",
      joinOperator: JoinOperator.LeftOuter);
linkToContact.EntityAlias = "co";

Consulte también

Consultar datos usando QueryExpression
Seleccionar columnas usando QueryExpression
Unir tablas usando QueryExpression
Ordenar filas usando QueryExpression
Filtrar filas usando QueryExpression
Resultados de la página usando QueryExpression
Agregar datos usando QueryExpression
Contar filas usando QueryExpression

Nota

¿Puede indicarnos sus preferencias de idioma de documentación? Realice una breve encuesta. (tenga en cuenta que esta encuesta está en inglés)

La encuesta durará unos siete minutos. No se recopilan datos personales (declaración de privacidad).