Die Leistung mit QueryExpression optimieren
In diesem Artikel werden Möglichkeiten beschrieben, wie Sie die Leistung beim Abrufen von Daten mit QueryExpression optimieren können.
Zu vermeidende Muster
Optimierte Abfragen für Dataverse zu erstellen, ist von entscheidender Bedeutung, um sicherzustellen, dass Anwendungen ein schnelles, reaktionsfähiges und zuverlässiges Erlebnis bieten. In diesem Abschnitt werden Muster und Konzepte vorgestellt, die man beim Erstellen von Abfragen für Standardtabellen mithilfe der RetrieveMultiple
-Nachricht oder von Nachrichten mit einem Parameter, der von der QueryBase-Klasse erbt, vermeiden bzw. kennen sollte. Diese Anleitung gilt auch beim Senden einer GET
Anfrage an eine Datensatzsammlung mithilfe von OData. Die hier aufgeführten Hinweise gelten möglicherweise nicht für elastische Tabellen oder bei Verwendung der Dataverse Suche.
Die Anzahl der ausgewählten Spalten minimieren
Nehmen Sie in Ihre Abfrage keine Spalten mit auf, die Sie nicht benötigen. Bei Abfragen, die alle Spalten zurückgeben oder eine große Anzahl von Spalten enthalten, können aufgrund der Größe des Datasets oder der Komplexität der Abfrage Leistungsprobleme auftreten.
Diese Vorgehensweise gilt insbesondere für logische Spalten. Eine logische Spalte enthält Werte, die in verschiedenen Datenbanktabellen gespeichert sind. Die AttributeMetadata.IsLogical-Eigenschaft gibt Ihnen Auskunft darüber, ob eine Spalte eine logische Spalte ist. Abfragen, die viele logische Spalten enthalten, sind langsamer, da Dataverse die Daten aus anderen Datenbanktabellen kombinieren muss.
Vorangestellte Platzhalter in Filterbedingungen vermeiden
Abfragen, die Bedingungen mit vorangestellten Platzhaltern verwenden (entweder explizit oder implizit mit einem Operator wie ends-with
), können zu Leistungseinbußen führen. Wenn eine Abfrage vorangestellte Platzhalter verwendet, kann Dataverse keine Datenbankindizes nutzen, sodass SQL gezwungen wird, die gesamte Tabelle zu scannen. Tabellenscans können selbst dann durchgeführt werden, wenn andere Abfragen mit nicht vorangestellten Platzhaltern vorhanden sind, die den Ergebnissatz einschränken.
Das folgende Beispiel ist ein FetchXml Bedingungselement, das einen vorangestellten Platzhalter verwendet:
<condition attribute='accountnumber'
operator='like'
value='%234' />
Das folgende Beispiel ist eine QueryExpression ConditionExpression, die einen vorangestellten Platzhalter verwendet:
new ConditionExpression("accountnumber", ConditionOperator.Like, "%234")
Das folgende Beispiel ist eine OData-Abfrage, die ein führendes Platzhalterzeichen Karte verwendet:
$filter=startswith(accountnumber,'%234')
Wenn bei Abfragen eine Zeitüberschreitung auftritt und dieses Muster erkannt wird, gibt Dataverse einen eindeutigen Fehler zurück, um zu ermitteln, welche Abfragen dieses Muster verwenden:
Name:
LeadingWildcardCauseTimeout
Code:0x80048573
Nummer:-2147187341
Meldung: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 drosselt Abfragen mit vorangestelltem Platzhalter, die als Risiko für die Integrität der Organisation identifiziert werden, stark, um Ausfälle zu verhindern. Weitere Informationen zur Abfragedrosselung
Wenn Sie häufig Abfragen mit vorangestellten Platzhaltern verwenden, prüfen Sie die folgenden Optionen:
- Verwenden Sie stattdessen die Dataverse-Suche.
- Ändern Sie Ihr Datenmodell, damit Benutzende auf vorangestellte Platzhalter verzichten können.
Weitere Informationen zum Verwenden von Platzhalterzeichen in Bedingungen für Zeichenfolgenwerte
Formeln oder berechneten Spalten in Filterbedingungen vermeiden
Die Werte von Formeln und berechneten Spalten werden in Echtzeit berechnet, wenn sie abgerufen werden. Abfragen, die Filter auf diese Spalten anwenden, zwingen Dataverse dazu, den Wert für jeden Datensatz, der möglicherweise zurückgegeben werden kann, zu berechnen, sodass der Filter angewendet werden kann. Die Abfragen sind langsamer, da Dataverse die Leistung dieser Abfragen nicht mit SQL verbessern kann.
Wenn bei Abfragen eine Zeitüberschreitung auftritt und dieses Muster erkannt wird, gibt Dataverse einen eindeutigen Fehler zurück, um zu ermitteln, welche Abfragen dieses Muster verwenden:
Name:
ComputedColumnCauseTimeout
Code:0x80048574
Nummer:-2147187340
Meldung: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.
Um Ausfälle zu vermeidet, drosselt Dataverse Abfragen, die Filter für berechnete Spalten enthalten, die als Risiko für die Integrität der Umgebung identifiziert wurden. Weitere Informationen zur Abfragedrosselung
Sortieren nach Auswahlspalten vermeiden
Wenn Sie FetchXml oder QueryExpression verwenden und Abfrageergebnisse mithilfe einer Auswahlspalte sortieren, werden die Ergebnisse mithilfe der lokalisierten Bezeichnung für jede Auswahloption sortiert. Die Sortierung nach dem in der Datenbank gespeicherten Zahlenwert würde in Ihrer Anwendung keine gute Erfahrung bieten. Seien Sie sich bewusst, dass das Sortieren nach Auswahlspalten mehr Rechenressourcen erfordert, um die Zeilen nach dem lokalisierten Beschriftungswert zu verknüpfen und zu sortieren. Dieser Mehraufwand verlangsamt die Abfrage. Vermeiden Sie wenn möglich die Sortierung der Ergebnisse nach Auswahlspaltenwerten.
Hinweis
OData ist anders. Mit der Dataverse Web-API $orderby
werden Zeilen anhand des ganzzahligen Werts der Auswahlspalte und nicht anhand der lokalisierten Bezeichnung sortiert.
Die Sortierung nach Spalten in zugehörigen Tabellen vermeiden
Das Sortieren nach Spalten in zugehörigen Tabellen verlangsamt die Abfrage aufgrund der zusätzlichen Komplexität.
Die Sortierung nach zugehörigen Tabellen sollte nur bei Bedarf erfolgen, wie hier beschrieben:
- Zeilen mithilfe von FetchXml anordnen
- Zeilen mithilfe von QueryExpression sortieren
- Zeilen mit OData sortieren
Bei großen Textspalten die Verwendung von Bedingungen vermeiden
Dataverse verfügt über zwei Spaltentypen, in denen große Textzeichenfolgen gespeichert werden können:
- StringAttributeMetadata kann bis zu 4.000 Zeichen speichern.
- MemoAttributeMetadata kann eine größere Anzahl speichern.
Der Grenzwert für diese beiden Spalten wird mit der Eigenschaft MaxLength
festgelegt.
Sie können Bedingungen auf Zeichenfolgenspalten anwenden, deren MaxLength
auf weniger als 850 Zeichen konfiguriert ist.
Alle Memospalten oder Zeichenfolgenspalten mit einem MaxLength
-Wert von über 850 werden in Dataverse als große Textspalten definiert. Große Textspalten sind für eine effektive Indizierung zu groß, was bei der Einbeziehung in eine Filterbedingung zu einer schlechten Leistung führt.
Dataverse Zum Abfragen von Daten in derartigen Spalten ist „search “ die bessere Wahl.
Abfragehinweise
Wichtig
Wenden Sie diese Optionen nur an, wenn dies vom technischen Microsoft-Support empfohlen wird. Eine falsche Verwendung dieser Optionen kann die Leistung einer Abfrage beeinträchtigen.
Microsoft SQL Server unterstützt viele Abfragehinweise zur Optimierung von Abfragen. QueryExpression unterstützt Abfragehinweise und kann diese Abfrageoptionen mithilfe der QueryExpression.QueryHints-Eigenschaft an SQL Server übergeben.
Abfrageoption | SQL Server-Hinweis |
---|---|
ForceOrder |
Befehl durchsetzen |
DisableRowGoal |
Hinweis: DISABLE_OPTIMIZER_ROWGOAL |
EnableOptimizerHotfixes |
Hinweis: ENABLE_QUERY_OPTIMIZER_HOTFIXES |
LoopJoin |
Loop verbinden |
MergeJoin |
Zusammenführen |
HashJoin |
Hash Join |
NO_PERFORMANCE_SPOOL |
NO_PERFORMANCE_SPOOL |
ENABLE_HIST_AMENDMENT_FOR_ASC_KEYS |
Hinweis: ENABLE_HIST_AMENDMENT_FOR_ASC_KEYS |
Weitere Informationen: Hinweise (Transact-SQL) – Abfrage
Keine Sperre
In früheren Versionen diente die QueryExpression.NoLock-Eigenschaft dazu, gemeinsame Sperren für Datensätze zu verhindern. Es ist nicht mehr notwendig, diese Eigenschaft einzuschließen
Vereinigungshinweis
Sie können die Leistung verbessern, wenn Sie eine FilterExpression hinzufügen, welche die ConditionExpression
für Spalten in verschiedenen Tabellen festlegt, indem Sie die FilterExpression.FilterHint-Eigenschaft auf union
festlegen. Es gibt jedoch einige Einschränkungen:
- Der FilterExpression.FilterOperator muss den LogicalOperator
.Or
verwenden. - Jede Abfrage kann nur einen
union
-Hinweis enthalten. - Wenn sich eine
FilterExpression
mit demunion
-Hinweis nicht im Filter der obersten Ebene befindet, wandelt Dataverse die Abfrage um und verschiebt den Filter mit einemunion
-Hinweis zum Stammfilter. - Wenn ein
union
-Hinweis mehr als drei Ebenen hat, wird er ignoriert.
Im folgenden Beispiel wird ein Filter mit einem union
-Hinweis auf die telephone1
-Spalte für beide Konto- und Kontakt-Tabellen festgelegt.
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";
Siehe auch
Daten mithilfe von QueryExpression abfragen
Spalten mit QueryExpression auswählen
Tabellen mit QueryExpression verknüpfen
Zeilen mithilfe von QueryExpression sortieren
Zeilen mithilfe von QueryExpression filtern
Paging von Ergebnissen mit QueryExpression
Daten mithilfe von QueryExpression aggregieren
Zeilen mithilfe von QueryExpression zählen
Hinweis
Können Sie uns Ihre Präferenzen für die Dokumentationssprache mitteilen? Nehmen Sie an einer kurzen Umfrage teil. (Beachten Sie, dass diese Umfrage auf Englisch ist.)
Die Umfrage dauert etwa sieben Minuten. Es werden keine personenbezogenen Daten erhoben. (Datenschutzbestimmungen).