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. Ces conseils s’appliquent également lors de l’envoi d’une requête sur une collection d’enregistrements à l’aide d’OData. GET
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")
L’exemple suivant est une requête OData qui utilise un caractère générique de début carte :
$filter=startswith(accountnumber,'%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.
É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 utilisez FetchXml ou QueryExpression, lorsque vous triez les résultats de la requête à l’aide d’une colonne de choix, les résultats sont triés à l’aide 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.
Notes
OData est différent. Avec l’ Dataverse API Web, $orderby
trie les lignes à l’aide de la valeur entière de la colonne de choix plutôt que de l’étiquette localisée.
É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 :
- Trier des lignes à l’aide de FetchXml
- Ordonner les lignes à l’aide de QueryExpression
- Trier les lignes à l’aide d’OData
É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 :
- StringAttributeMetadata peuvent stocker un maximum de 4 000 caractères.
- MemoAttributeMetadata peut stocker un nombre plus élevé.
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 |
---|---|
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 conseilunion
n’est pas au niveau du filtre supérieur, Dataverse transforme la requête et déplace le filtre avec ununion
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é).