Partage via


Optimiser les performances à l’aide de QueryExpression

Cet article décrit les façons dont vous pouvez optimiser les performances lors de la récupération de données à l’aide de QueryExpression.

Modèles à éviter

La composition de requêtes optimisées pour Dataverse est essentielle pour garantir que les applications offrent une expérience rapide, réactive et fiable. Cette section décrit les modèles à éviter et les concepts à comprendre lors de la composition de requêtes pour des tables standard à l’aide du RetrieveMultiple message ou de messages dont le paramètre hérite de la classe QueryBase. Les conseils présentés ici peuvent ne pas s’appliquer aux tableaux Elastic ou lors de l’utilisation de Dataverse recherche.

Minimiser le nombre de colonnes sélectionnées

N’incluez pas les colonnes dont vous n’avez pas besoin dans votre requête. Les requêtes qui renvoient toutes les colonnes ou incluent un grand nombre de colonnes peuvent rencontrer des problèmes de performances en raison de la taille du jeu de données ou de la complexité de la requête.

Cette pratique est particulièrement vraie pour les colonnes logiques. Une colonne logique contient des valeurs stockées dans différentes tables de base de données. La propriété AttributeMetadata.IsLogical vous indique si une colonne est une colonne logique. Les requêtes qui contiennent de nombreuses colonnes logiques sont plus lentes car Dataverse doivent combiner les données d’autres tables de base de données.

Évitez les caractères génériques en tête dans les conditions de filtrage

Les requêtes qui utilisent des conditions avec des caractères génériques de début (soit explicitement, soit implicitement avec un opérateur tel que ends-with) peuvent entraîner de mauvaises performances. Dataverse ne peut pas profiter des index de base de données lors d’une requête utilisant des caractères génériques de premier plan, ce qui oblige SQL à analyser la table entière. Les analyses de table peuvent avoir lieu même s’il existe d’autres requêtes génériques non principales qui limitent l’ensemble de résultats.

L’exemple suivant est un élément de condition FetchXml qui utilise un caractère générique de début :

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

L’exemple suivant est un QueryExpression ConditionExpression qui utilise un caractère générique de début :

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

Lorsque le délai d’attente des requêtes expire et que ce modèle est détecté, Dataverse renvoie une erreur unique pour aider à identifier les requêtes qui utilisent ce modèle :

Nom: LeadingWildcardCauseTimeout
Code : 0x80048573
Nombre : -2147187341
Message : 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 limite fortement les principales requêtes génériques identifiées comme un risque pour la santé de l’organisation afin d’aider à prévenir les pannes. En savoir plus sur les limitation de requêtes

Si vous utilisez des requêtes génériques de premier plan, étudiez ces options :

  • Utiliser Dataverse la recherche à la place.
  • Modifiez votre modèle de données pour aider les gens à éviter d’avoir besoin de caractères génériques de premier plan.

En savoir plus sur l’utilisation de caractères génériques dans les conditions pour les valeurs de chaîne

Évitez d’utiliser des formules ou des colonnes calculées dans des conditions de filtre

Les valeurs des formules et colonnes calculées en temps réel quand elles sont récupérées. Les requêtes qui utilisent des filtres sur ces colonnes obligent Dataverse à calculer la valeur de chaque enregistrement possible pouvant être renvoyé afin que le filtre puisse être appliqué. Les requêtes sont plus lentes car Dataverse ne peut pas améliorer les performances de ces requêtes à l’aide de SQL.

Lorsque le délai d’attente des requêtes expire et que ce modèle est détecté, Dataverse renvoie une erreur unique pour aider à identifier les requêtes qui utilisent ce modèle :

Nom: ComputedColumnCauseTimeout
Code : 0x80048574
Nombre : -2147187340
Message : 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.

Pour éviter les pannes, Dataverse applique des limitations aux requêtes comportant des filtres sur les colonnes calculées identifiées comme présentant un risque pour la santé de l’environnement. En savoir plus sur les limitation de requêtes

Évitez de trier par colonnes de choix

Lorsque vous classez les résultats d’une requête à l’aide d’une colonne de choix, les résultats sont triés en fonction de l’étiquette localisée pour chaque option de choix. Trier par la valeur numérique stockée dans la base de données ne fournirait pas une bonne expérience dans votre application. Vous devez savoir que le classement des colonnes de choix nécessite davantage de ressources de calcul pour joindre et trier les lignes en fonction de la valeur d’étiquette localisée. Ce travail supplémentaire ralentit la requête. Si possible, essayez d’éviter de trier les résultats par valeurs de colonne de choix.

Évitez de trier par colonnes dans les tables associées

Le classement par colonnes sur les tables associées ralentit la requête en raison de la complexité supplémentaire.

Le classement par tables associées ne doit être effectué qu’en cas de besoin, comme décrit ici :

Évitez d’utiliser des conditions sur de grandes colonnes de texte

Dataverse dispose de deux types de colonnes pouvant stocker de grandes chaînes de texte :

La limite pour ces deux colonnes est spécifiée à l’aide de la propriété MaxLength .

Vous pouvez utiliser des conditions sur les colonnes de chaîne dont a MaxLength est configuré pour moins de 850 caractères.

Toutes les colonnes mémo ou colonnes de chaîne avec un MaxLength supérieur à 850 sont définies dans Dataverse en tant que grandes colonnes de texte. Les grandes colonnes de texte sont trop volumineuses pour être indexées efficacement, ce qui entraîne de mauvaises performances lorsqu’elles sont incluses dans une condition de filtre.

Dataverse La recherche est un meilleur choix pour interroger des données dans ce type de colonnes.

Indicateurs de requête

Important

Appliquez ces options uniquement lorsqu’elles sont recommandées par le support technique Microsoft. Une utilisation incorrecte de ces options peut dégrader les performances d’une requête.

Microsoft SQL Server prend en charge plusieurs indicateurs de requête pour optimiser les requêtes. QueryExpression Le langage FetchXML prend en charge les indicateurs de requête et peut transmettre ces options de requête à SQL Server avec propriété QueryExpression.QueryHints.

Option de requête Conseil SQL Server
OptimizeForUnknown Optimiser pour inconnu
ForceOrder Forcer l’ordre
DisableRowGoal Conseil : DISABLE_OPTIMIZER_ROWGOAL
EnableOptimizerHotfixes Conseil : ENABLE_QUERY_OPTIMIZER_HOTFIXES
LoopJoin Mettre en boucle la jonction
MergeJoin Fusionner la jonction
HashJoin Hacher la jonction
NO_PERFORMANCE_SPOOL NO_PERFORMANCE_SPOOL
ENABLE_HIST_AMENDMENT_FOR_ASC_KEYS Conseil : ENABLE_HIST_AMENDMENT_FOR_ASC_KEYS

Plus d’information : Conseils (Transact-SQL) - Requête

Aucun verrou

Dans les versions antérieures, la propriété QueryExpression.NoLock utilisée pour empêcher les verrous partagés sur les enregistrements. Il n’est plus nécessaire d’inclure cette propriété

Indicateur d’union

Vous pouvez améliorer les performances en ajoutant un FilterExpression qui définit le ConditionExpression des colonnes dans différentes tables en définissant le FilterExpression.FilterHint propriété à union. Mais certaines restrictions s’appliquent :

  • Le FilterExpression.FilterOperator doit utiliser LogicalOperator.Or.
  • Chaque requête ne peut contenir qu’un seul indicateur union.
  • Si un FilterExpression avec conseil union n’est pas au niveau du filtre supérieur, Dataverse transforme la requête et déplace le filtre avec un union conseil au filtre racine.
  • Si un indicateur union dispose de plus de trois niveaux de profondeur, il est ignoré.

L’exemple suivant définit un filtre avec l’indicateur union sur la colonne telephone1 à la fois pour les tables compte et contact.

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";

Voir aussi

Interroger les données à l’aide de QueryExpression
Sélectionner des colonnes à l’aide de QueryExpression
Joindre des tables à l’aide de QueryExpression
Ordonner les lignes à l’aide de QueryExpression
Filtrer les lignes à l’aide de QueryExpression
Résultats de page à l’aide de QueryExpression
Agréger les données à l’aide de QueryExpression
Compter les lignes à l’aide de QueryExpression

Notes

Pouvez-vous nous indiquer vos préférences de langue pour la documentation ? Répondez à un court questionnaire. (veuillez noter que ce questionnaire est en anglais)

Le questionnaire vous prendra environ sept minutes. Aucune donnée personnelle n’est collectée (déclaration de confidentialité).