LIKE vs CONTAINS auf SQL Server

209

Welche der folgenden Abfragen ist schneller (LIKE vs CONTAINS)?

SELECT * FROM table WHERE Column LIKE '%test%';

oder

SELECT * FROM table WHERE Contains(Column, "test");
user667429
quelle
12
Akzeptieren Sie eine Antwort, oder?
AgentFire
7
Er war seit Jahren nicht mehr auf Mann.
Chris

Antworten:

174

Die zweite (vorausgesetzt, Sie meinen CONTAINS, und tatsächlich in eine gültige Abfrage einfügen) sollte schneller sein, da sie eine Art Index verwenden kann (in diesem Fall einen Volltextindex). Diese Form der Abfrage ist natürlich nur verfügbar, wenn sich die Spalte in einem Volltextindex befindet. Ist dies nicht der Fall, ist nur das erste Formular verfügbar.

Die erste Abfrage, die LIKE verwendet, kann keinen Index verwenden, da sie mit einem Platzhalter beginnt und daher immer einen vollständigen Tabellenscan erfordert.


Die CONTAINSAbfrage sollte lauten:

SELECT * FROM table WHERE CONTAINS(Column, 'test');
Damien_The_Unbeliever
quelle
@edze - du meinst, die gleiche Seite, die bereits verlinkt ist, ist meine erste Erwähnung CONTAINS? Was davon? Die ursprüngliche Form der Frage hatte, Column CONTAIN("%test%",Column)>0die nirgends annähernd gültig war. Es ist immer noch nicht ganz richtig.
Damien_The_Unbeliever
Dies hat uns geholfen, eine Abfrage in SharePoint zu sortieren. Haben Sie ein anderes großes Antwortabzeichen.
Ouflak
14

Nachdem ich beide Abfragen auf einer SQL Server 2012-Instanz ausgeführt habe, kann ich bestätigen, dass die erste Abfrage in meinem Fall am schnellsten war.

Die Abfrage mit dem LIKESchlüsselwort zeigte einen Clustered-Index-Scan.

Das CONTAINShatte auch einen Clustered-Index-Scan mit zusätzlichen Operatoren für die Volltextübereinstimmung und einen Merge-Join.

Planen

MI C.
quelle
8
Die gruppierten Indexblattseiten sind die Tabelle. Eine LIKEAbfrage mit einem führenden Platzhalter kann den Indexteil nicht effizient verwenden. Es muss nur das Ganze gescannt werden. Obwohl es zweifellos einige Umstände gibt, unter denen der vollständige CI-Scan eine bessere Leistung erbringt als eine Abfrage unter Verwendung des Volltextindex (möglicherweise, wenn beispielsweise ein sehr hoher Anteil der Zeilen übereinstimmt), ist dies größtenteils die Ausnahme, die Sie nicht bestätigen können ".
Martin Smith
Nun, ich schaue mir einen tatsächlichen Ausführungsplan an, der über 200.000 Datensätze abruft. Wenn beide Abfragen in einem Stapel zusammengefasst wurden, haben beide den Clustered-Index gescannt. Zusätzlich verursacht die Abfrage "CONTAINS" zusätzliche Kosten für FULL TEXT MATCH und einen MERGE JOIN.
MI C
Wenn ein Zusammenführungs-Join ausgewählt wird, schätzt SQL Server, dass mehr als x% der Zeilen mit dem Prädikat übereinstimmen. (Wobei X = der Wendepunkt ist ). In diesem Fall würde ich mir vorstellen, dass beide ziemlich gleichmäßig zusammenpassen könnten. Die im Ausführungsplan angegebenen Kosten sind nur Schätzungen (auch im tatsächlichen Plan). Der FT-Plan enthält zwar zusätzliche Betreiber von Ausführungsplänen, bietet jedoch einige Vorteile. Der Merge-Join kann vor dem Ende des Scans angehalten werden, wenn die FT-Ergebnisse ausgehen und er auch nicht ausgewertet werden muss LIKE.
Martin Smith
1
Ich habe eine ähnliche Abfrage ausgeführt, um den Ausführungsplan in SQL 2012 zu überprüfen, und es gab mir eine Indexsuche. Vielleicht war der Tisch im Beispiel hier fast leer. In einigen Fällen verwendet SQL stattdessen einen Index-Scan in einer sehr kleinen Tabelle, um den Index zu verwenden, da dieser schneller ist.
Juan
8

Ich denke, CONTAINSdas hat länger gedauert und verwendet, Mergeweil Sie einen Bindestrich ("-") in Ihrer Abfrage hatten adventure-works.com.

Der Bindestrich ist ein Unterbrechungswort, daher wurde im CONTAINSVolltextindex adventurenach works.comden Ergebnissen gesucht und danach gesucht und die Ergebnisse zusammengeführt.

Omri Valfer
quelle
8

Versuchen Sie auch, dies zu ändern:

    SELECT * FROM table WHERE Contains(Column, "test") > 0;

Dazu:

    SELECT * FROM table WHERE Contains(Column, '"*test*"') > 0;

Ersteres findet Datensätze mit Werten wie " Dies ist ein Test " und " Ein Testfall ist der Plan ".

Letztere finden auch Datensätze mit Werten wie " Ich teste dies " und " Dies ist das Größte ".

John Doe
quelle
4
Funktioniert das Setzen des Sterns vor und nach dem Suchbegriff? Beim Lesen der Dokumentation für CONTAINSwerden nur Präfixbegriffe wie "test *", keine Suffixbegriffe wie " test" und keine vollständige Teilstringsuche wie "* test " erwähnt. Ich habe es jedoch nicht versucht.
Matt Forsythe
4
Wenn Sie die Dokumentation zu CONTAINS ( docs.microsoft.com/en-us/sql/t-sql/queries/… ) lesen , wird nur die Suche nach Präfixen unterstützt. Ich habe dies mehrfach experimentell versucht und es ist nicht möglich, "Dies ist das Größte" (in SQL Server) mit Contains (Spalte, " Test ") zu finden
cl0rkster