Abfrageleistung optimieren

Verwenden Sie zur Fehlerbehebung bei langsamen Abfragen Query Explain, um den Abfrageausführungsplan und das Laufzeitausführungsprofil abzurufen. Im folgenden Abschnitt werden Schritte beschrieben, mit denen Sie die Abfrageleistung je nach Ausführungsprofil optimieren können:

Anzahl der Ergebnisse begrenzen

Anhand des Felds „Zurückgegebene Datensätze“ im Ausführungsbaum können Sie feststellen, ob die Abfrage viele Dokumente zurückgibt. Sie können die Anzahl der zurückgegebenen Dokumente mit der $limit-Klausel begrenzen. Dadurch wird die serialisierte Byte-Größe der Ergebnisse reduziert, wenn sie über das Netzwerk an die Clients zurückgegeben werden. Wenn dem Limit-Knoten ein MajorSort-Knoten vorangestellt ist, kann die Abfrage-Engine den Limit- und den MajorSort-Knoten zusammenführen und eine vollständige In-Memory-Materialisierung und Sortierung durch eine TopN-Sortierung ersetzen, wodurch der Arbeitsspeicherbedarf für die Abfrage reduziert wird.

Größe des Ergebnisdokuments begrenzen

Sie können die Größe des zurückgegebenen Dokuments mit der $project-Klausel begrenzen, um das Abrufen unnötiger Felder zu vermeiden. Dadurch werden die Rechen- und Speicherkosten für die Verarbeitung von Zwischenergebnissen und die serialisierte Bytegröße der Ergebnisse reduziert, wenn sie über das Netzwerk an die Clients zurückgegeben werden. Wenn alle in der Abfrage referenzierten Felder von einem regulären Index (kein Multikey-Index) abgedeckt werden, kann die Abfrage auch vollständig durch den Indexscan abgedeckt werden. Dadurch müssen keine Dokumente aus dem primären Speicher abgerufen werden.

Indexe verwenden

So richten Sie Indexe ein und optimieren sie:

Prüfen, ob die Abfrage einen Index verwendet

Sie können feststellen, ob die Abfrage einen Index verwendet, indem Sie die Blattknoten im Ausführungsbaum prüfen. Wenn der Blattknoten des Ausführungsbaums ein TableScan-Knoten ist, bedeutet dies, dass die Abfrage keinen Index verwendet und Dokumente aus dem primären Speicher scannt. Wenn ein Index verwendet wird, werden im Blattknoten des Ausführungsbaums die Index-ID und die Indexfelder des Index angezeigt.

Prüfen, ob der verwendete Index optimiert werden kann

Ein Index ist für eine Abfrage nützlich, wenn er die Anzahl der Dokumente reduzieren kann, die die Abfrage-Engine aus dem primären Speicher abrufen muss, oder wenn die Feldreihenfolge die Sortieranforderung der Abfrage erfüllen kann.

Wenn ein Index für eine Abfrage verwendet wird, die Abfrage-Engine aber immer noch viele Dokumente abruft und verwirft, was durch einen Scan-Knoten, der viele Datensätze zurückgibt, gefolgt von einem Filterknoten, der wenige Datensätze zurückgibt, erkennbar ist, ist das ein Zeichen dafür, dass das mit dem Index erfüllte Abfrageprädikat nicht selektiv ist. Informationen zum Erstellen eines geeigneteren Index finden Sie unter Indexe erstellen.

Wenn für eine Abfrage ein Index verwendet wird, der kein Multikey-Index ist, die Abfrage-Engine aber dennoch eine Neuanordnung der Ergebnismenge im Arbeitsspeicher vornimmt, was durch einen MajorSort-Knoten im Abfrageausführungsbaum angezeigt wird, ist dies ein Zeichen dafür, dass der verwendete Index nicht zur Erfüllung der Sortieranforderung der Abfrage verwendet werden kann. Informationen zum Erstellen eines geeigneteren Index finden Sie im nächsten Abschnitt.

$lookup-Abfragen optimieren

Sie können $lookup-Abfragen optimieren, indem Sie der Sammlung from Indexe hinzufügen. Dadurch kann der Vorgang übereinstimmende Dokumente effizient finden, ohne die gesamte Sammlung zu scannen.

$lookup mit localField und foreignField

Wenn Sie die Optionen localField und foreignField in der Phase $lookup verwenden, erstellen Sie einen Index für foreignField in der Sammlung from.

$lookup mit verschachtelten Pipelines

Wenn Sie die Option pipeline in der Phase $lookup mit $match-Phasen verwenden, erstellen Sie einen Index für die Felder, die in der externen Sammlung enthalten sind, um einen vollständigen Sammlungsscan zu vermeiden:

  • Erstellen Sie für $match-Phasen mit Filtersemantik (z. B. {$match: {a: true}}) einen Index für die Felder, die in der externen Sammlung (a) enthalten sind.
  • Erstellen Sie für $match-Phasen mit Aggregationssemantik, die ein Feld mit einem konstanten Wert (z. B. {$match: {$expr: {$gt: [a, 10]}}}) oder mit Gleichheitsvergleichen (eq oder in) zwischen Feldern und Variablen vergleicht, die in let definiert sind (z. B. {$match: {$expr: {$eq: [a, "$$a"]}}}), einen Index für die Felder, die in der externen Sammlung enthalten sind. Beachten Sie, dass der Multikey-Index bei der Planung nicht verwendet wird.

Indexe erstellen

Folgen Sie der Dokumentation zur Indexverwaltung, um Indexe zu erstellen. Damit Ihre Abfrage Indexe verwenden kann, erstellen Sie reguläre Indexe (keine Multikey-Indexe) mit Feldern in der folgenden Reihenfolge:

  1. Alle Felder, die in Gleichheitsoperatoren verwendet werden. Wenn Sie die Wahrscheinlichkeit einer Wiederverwendung über Abfragen hinweg maximieren möchten, ordnen Sie die Felder in absteigender Reihenfolge des Vorkommens der Felder in Gleichheitsoperatoren zwischen Abfragen an.
  2. Alle Felder, nach denen sortiert wird (in derselben Reihenfolge).
  3. Felder, die in Bereichs- oder Ungleichheitsoperatoren in absteigender Reihenfolge der Selektivität der Abfrageeinschränkung verwendet werden.
  4. Felder, die als Teil einer Abfrage im Index zurückgegeben werden: Wenn Sie solche Felder in den Index aufnehmen, kann der Index die Abfrage abdecken und es muss kein Dokument aus dem primären Speicher abgerufen werden.

Für Abfragen, die das Filtern und Sortieren von Array-Feldern beinhalten, sollten Sie Multikey-Indizes erstellen.

Abfragehinweis verwenden

Wenn Sie einen besser geeigneten Index für die Abfrage erstellt haben, die Abfrage-Engine diesen Index jedoch nicht verwendet, können Sie die Indexpräferenz der Abfrage-Engine mit einem Abfragehinweis überschreiben.

Weitere Informationen zur Ausgabe einer Abfrage, die mit Query Explain ausgeführt wurde, finden Sie in der Referenz zur Abfrageausführung.