Verbessern der Leistung von Volltextabfragen in SQL Server

Dieser Artikel enthält eine Methode zum Verbessern der Leistung von Abfragen, die Volltext-Prädikate in SQL Server verwenden.

Ursprüngliche Produktversion: SQL Server 2008 Developer, SQL Server 2008 Enterprise, SQL Server 2008 R2 Datacenter, SQL Server 2008 R2 Developer, SQL Server 2008 R2 Enterprise, SQL Server 2008 R2 Standard, SQL Server 2012 Developer, SQL Server 2012 Standard, SQL Server 2012 Web, SQL Server 2012 Enterprise
Ursprüngliche KB-Nummer: 2549443

Zusammenfassung

In diesem Artikel wird eine Methode zum Verbessern der Leistung von Microsoft SQL Server-Abfragen beschrieben, die Volltextsuch-Prädikate (zCONTAINS. B. und CONTAINSTABLE) verwenden und auch Daten filtern. Diese Methode verbessert beispielsweise die Leistung der folgenden Abfrage:

SELECT * FROM dbo.ftTest WHERE CONTAINS(TextData, '"keyword"') AND CDate > @date

Mit dieser Methode können Sie die Abfrage, das Tabellenschema und den Volltextindex so entwerfen, dass die Volltextsuchmaschine Ergebnisse herausfiltert, bevor sie an die relationale Engine gesendet werden. Daher muss die relationale Engine kein großes Dataset filtern.

Weitere Informationen

Wenn Sie eine Volltextsuchabfrage erstellen, ist der Hauptfaktor, der sich auf die Leistung der Abfrage auswirkt, die Menge der Daten, die die Volltextsuchmaschine verarbeiten muss, bevor die verbleibenden Daten an die relationale Engine gesendet werden. In SQL Server können Sie die Leistung der Abfrage verbessern, indem Sie Zeilen frühzeitig herausfiltern, um die Anzahl der Zeilen zu reduzieren, die später verarbeitet werden müssen.

In Versionen von SQL Server, die vor SQL Server 2008 veröffentlicht wurden, gibt die Volltextsuchmaschine alle Zeilen zurück, die einem Suchbegriff entsprechen, und dann wendet die relationale Engine alle Filter an. Dieses Verhalten wurde im SQL Server 2008, im SQL Server 2008 R2 und im SQL Server 2012 verbessert. Es ist jedoch schwierig, diese Verbesserungen zu verwenden, da Volltextsuchindizes anders organisiert sind als Datenbankindizes. Darüber hinaus funktionieren die Volltextsuchmaschine und die relationale Engine anders. Daher verwendet die in diesem Artikel beschriebene Methode die Table-Valued-Funktion (TVF), um Zeilen frühzeitig herauszufiltern und die Anzahl der Zeilen zu reduzieren, die später verarbeitet werden müssen.

Der folgende Abfrageplan gibt beispielsweise 131051 Zeilen zurück, die mit einer CONTAINS Suchzeichenfolge übereinstimmen. Darüber hinaus führt ein Joinoperator im Plan mithilfe einer Indexsuche zusätzliche Filterung durch.

Rows StmtText
-------------------- ----------------------------------------------------------------------------------------
1167 SELECT CDate, ID FROM dbo.fttest WHERE contains (c2, '"create"') AND CDate> '08/05/2019'

1167 |--Merge Join(Left Semi Join, MERGE:([FTSdb].[dbo].[fttest].[ID])=(FulltextMatch.[docid]), RESIDUA
5858 |--Sort(ORDER BY:([FTSdb].[dbo].[fttest].[ID] ASC))
5858 | |--Clustered Index Seek(OBJECT:([FTSdb].[dbo].[fttest].[clidx1]), SEEK:([FTSdb].[
131051 |--Table-valued function

Wenn die Abfrage jedoch die Volltextschlüsselspalte für eindeutige Indexschlüssel als Prädikat enthält, kann die Volltextsuchmaschine das Prädikat verwenden, um Ergebnisse auf Volltextebene zu filtern. In diesem Fall gibt der TVF eine viel kleinere Datenmenge zurück, bevor eine zusätzliche Filterung angewendet werden muss. Die folgende Abfrage gibt beispielsweise fünf Werte an, die der c2-Bedingung entsprechen müssen, und der TVF gibt nur die Ergebnisse zurück, die den fünf Werten entsprechen:

Rows StmtText
-------------------------------------------------------------------------------------------------------------------------------------------
5 SELECT CDate, ID FROM dbo.fttest WHERE contains (c2, '"create"') AND CDate > '08/05/2019' AND ID IN ( 654051, 644051, 649106, 465, 105)

5 |--Nested Loops(Left Semi Join, OUTER REFERENCES:([FTSdb].[dbo].[fttest].[ID]))
5 |--Index Seek(OBJECT:([FTSdb].[dbo].[fttest].[idx1]), SEEK:([FTSdb].[dbo].[fttest].[ID]=(105) OR ...
5 |--Table-valued function

Die Möglichkeit der Volltextsuchmaschine, die werte, die vom eindeutigen Indexschlüssel verwendet werden, zu pushen, ist die Grundlage der folgenden Methode.

Wenn ein Prädikat eine DateTime Datentypspalte enthält, können Sie Datumsinformationen in die Eindeutige Indexschlüsselspalte einschließen, sodass nur die Zeilen zurückgegeben werden, die mit diesem Prädikat übereinstimmen. Dazu müssen Sie die Datumsinformationen logisch in die Schlüsselspalte integrieren. Möglicherweise müssen Sie jedoch auch den Datentyp der Schlüsselspalte und die Anwendungen ändern, die die Abfrage verwenden.

Um die -Methode zu implementieren, ändern Sie den Datentyp des eindeutigen Volltextschlüssels ID in BIGINT. Die ersten vier Bytes der Schlüssel-ID erfassen die Werte für Jahr, Monat und Datum aus der Datumsspalte, und die letzten vier Bytes bleiben gleich. Beispielsweise kann das erste Byte der Schlüssel-ID auf das Jahr verweisen, das nächste Byte könnte auf den Monat verweisen, und die letzten 2 Bytes können auf das Datum verweisen. Die Anwendung muss diese Datentypänderung berücksichtigen.

Übersetzen Sie dann ein Bereichsprädikat in ein Prädikat für die Schlüssel-ID. Beispielsweise kann das x < CDate < y Bereichsprädikat in das (x*2^32 < ID < y*2^32) Prädikat übersetzt werden. Da das übersetzte Prädikat ein Prädikat für die Volltexttaste ist, wird das Prädikat in den Volltextstreaming Table-Valued Functions (STVF) gepusht. Dieses Verhalten führt effektiv Suchvorgänge innerhalb des Datumsbereichs durch.