Frage

Die Produkttabelle hat 700K Datensätze drin. Die Abfrage:

SELECT TOP 1 ID, Name FROM Product WHERE contains(Name, '"White Dress"') ORDER BY DateMadeNew desc

dauert ca. 1 Minute laufen. Es ist ein nicht-gruppierten Index für DateMadeNew und Freetext-Index für Namen.

Wenn ich TOP 1 oder bestellen entfernen -. Es dauert weniger als 1 Sekunde bis Lauf

Hier ist der Link zum Ausführungsplan. http://screencast.com/t/ZDczMzg5N

Sieht aus wie FullTextMatch hat über 400K Hinrichtung. Warum passiert dies? Wie kann es schneller gemacht werden?

UPDATE 2010.05.03

Sieht aus wie Mächtigkeit ist aus auf Multi Wort Freetext sucht Whack:

Optimizer schätzt, dass es 28K Einträge mit ‚White Dress‘, während es in Wirklichkeit nur 1 ist. http://screencast.com/t/NjM3ZjE4NjAt

Wenn ich 'Weißes Kleid' mit 'White' ersetzen, geschätzter Zahl ist '27, 951' , während tatsächliche Zahl '28 ist, 487' , die viel besser ist.

Es scheint, wie Optimizer verwendet, wird nur das erste Wort in Satz für Mächtigkeit gesucht.

War es hilfreich?

Lösung

Bearbeiten

http://technet.microsoft.com/en- us / library / cc721269.aspx # _Toc202506240

Das Wichtigste ist, dass die korrekter Join-Typ wird gepflückt für Volltextabfrage. Cardinality Schätzung auf der FulltextMatch STVF ist sehr wichtig für den richtigen Plan. Das erste, was zu überprüfen ist, die FulltextMatch Mächtigkeit Schätzung. Dies ist die geschätzte Anzahl der Treffer im Index für die Volltextsuche String. Zum Beispiel in der Abfrage in Abbildung 3 soll dies auf das seinem enge Anzahl der Dokumente, die die Begriff ‚Wort‘. In den meisten Fällen sollte es sehr genau, aber wenn die Schätzung durch einen langen Weg war weg, könnte man erzeugen schlechte Pläne. Die Schätzung für einzelne Begriffe sind in der Regel sehr gut, Abschätzen aber mehrere Begriffe wie Phrasen oder und Abfragen sind komplexe da ist es nicht möglich zu wissen, was der Schnittpunkt der Begriffe im Index wird auf der Frequenz des basieren Begriffe im Index. Wenn die Kardinalität Schätzung ist gut, ein schlechter Plan wahrscheinlich wird durch die Abfrage verursacht Optimierer Kostenmodell. Der einzige Weg, den Plan Problem beheben ist, eine Abfrage zu verwenden Hinweis eine bestimmte Art zu zwingen, der beitreten oder OPTIMIZE FOR.

So kann es einfach nicht, aus den Informationen speichern, ob die zwei Begriffe zusammen wahrscheinlich ganz unabhängig oder häufig zusammen gefunden werden. Vielleicht sollten Sie zwei getrennte Verfahren für einzelne Wort Abfragen eine haben, dass Sie die Optimierers auf seine Sachen machen lassen und eine für Multi Wort Verfahren, dass Sie auf (sys.dm_fts_index_keywords ein „gut genug“ Plan zwingen könnte helfen, wenn Sie nicht über eine wollen one size fits all Plan).

NB:. Ihr einziges Wort Verfahren würde die Option WITH RECOMPILE wahrscheinlich müssen in diesem Bit des Artikels suchen

In SQL Server 2008 Volltextsuche wir die Möglichkeit haben, den Plan zu ändern, die verwendet basierend auf einer Mächtigkeit Schätzung des Suchbegriffs erzeugt wird. Wenn der Abfrage-Plan festgelegt ist (wie es in einer parametrisierten Abfrage innerhalb einer gespeicherten Prozedur ist), ist dieser Schritt nicht stattfinden. Daher dient der kompilierte Plan immer diese Abfrage, auch wenn dieser Plan für einen bestimmten Suchbegriff nicht ideal ist.

Original Antwort

Ihr neuer Plan sieht immer noch ziemlich schlecht aber. Es sieht aus wie es nur 1 Zeile aus dem Volltextabfrageteil der Rückkehr aber das Scannen alle 770.159 Zeilen in der Product-Tabelle.

Wie wirkt sich das durchführen?

CREATE TABLE #tempResults
(
ID int primary key,
Name varchar(200),
DateMadeNew datetime
)

INSERT INTO #tempResults
SELECT 
      ID, Name, DateMadeNew 
      FROM Product 
      WHERE contains(Name, '"White Dress"')


SELECT TOP 1
    *
    FROM #tempResults
    ORDER BY DateMadeNew desc

Andere Tipps

Ich kann nicht sehen, den verknüpfte Ausführungsplan, Netz Polizei, dass blockieren, so dass dies nur eine Vermutung ist ...

, wenn es schnell ohne TOP und ORDER BY ausgeführt wird, versuchen dies zu tun:

SELECT TOP 1
    *
    FROM (SELECT 
              ID, Name, DateMadeNew 
              FROM Product 
              WHERE contains(Name, '"White Dress"')
         ) dt
    ORDER BY DateMadeNew desc

Sieht aus wie FullTextMatch hat über 400K Hinrichtung. Warum ist das passiert?

Da Sie einen Index mit TOP 1 kombiniert haben, Optimierer denkt, dass es besser sein wird, um den Index zu durchqueren, jeden Datensatz für den Eintrag zu überprüfen.

Wie kann es schneller gemacht werden?

Wenn die Statistiken Aktualisierung nicht hilft, versuchen Sie einen Hinweis auf Ihre Frage hinzufügen:

SELECT  TOP 1 *
FROM    product pt
WHERE   CONTAINS(name, '"test1"')
ORDER BY
        datemadenew DESC
OPTION (HASH JOIN)

Damit wird den Motor zwingen, einen HASH JOIN Algorithmus zu verwenden, um Ihre Tabelle und die Ausgabe der Volltext-Abfrage zu verbinden.

Volltext Abfrage als eine entfernte Quelle betrachtet wird, um die Menge von Werten indiziert durch KEY INDEX in der FULLTEXT INDEX Definition bereitgestellt zurück.

Update:

Wenn Ihre ORM Anwendungen Abfragen parametrisiert, können Sie einen Plan Leitfaden erstellen.

  • Verwenden Profiler zu Intercept die Abfrage, dass der ORM sendet wörtlich
  • Erstellen Sie einen richtigen Plan in SSMS Hinweise verwenden und speichern Sie es als XML
  • Verwenden Sie sp_create_plan_guide mit einem OPTION USE PLAN den Optimierer zu zwingen, immer diesen Plan verwenden.

Ich hatte das gleiche Problem früher.

Die Leistung ist abhängig von der eindeutigen Index Sie für die Volltextindizierung wählen. Meine Tabelle hat zwei eindeutige Spalten -. ID und article_number

Die Abfrage:

select top 50 id, article_number, name, ... 
from ARTICLE 
CONTAINS(*,'"BLACK*" AND "WHITE*"')
ORDER BY ARTICLE_NUMBER

Wenn der Volltextindex zu ID verbunden ist, dann ist es langsam, je nach den Worten gesucht. Wenn der Volltextindex zu ARTICLE_NUMBER UNIQUE Index verbunden ist dann immer schnell war.

habe ich eine bessere Lösung.

ich. Lassen Sie uns zunächst Überblick vorgeschlagenen Lösungen, wie sie auch in einigen Fällen verwendet werden:

  1. OPTION (HASH JOIN) - ist nicht gut, wie Sie Fehler erhalten kann "Query-Prozessor keinen Abfrage-Plan wegen der in dieser Abfrage definierten Hinweise erzeugen könnte Resubmit die Abfrage ohne irgendwelche Hinweise Angabe und ohne. mit SET FORCE. "

  2. SELECT TOP 1 * FROM (ORIGINAL_SELECT) ORDER BY ... - ist nicht gut, wenn Sie brauchen, um Paginieren Ergebnisse von Ihnen ORIGINAL_SELECT

  3. sp_create_plan_guide - ist nicht gut, wie zu verwenden plan_guide Sie Plan speichern für bestimmte SQL-Anweisung, das wird nicht funktionieren für dynamische SQL-Anweisungen (zum Beispiel durch ORM generieren)

II. Meine Lösung enthält zwei Teile 1. Selbst Join-Tabelle für die Volltextsuche verwendet 2. Verwenden Sie MS SQL Hashverknüpfung Hinweise MSDN Join Hinweise

Ihre SQL:

SELECT TOP 1 ID, Name FROM Product WHERE contains(Name, '"White Dress"') 
ORDER BY DateMadeNew desc

werden soll neu geschrieben als:

SELECT TOP 1 p.ID, p.Name FROM Product p INNER HASH JOIN Product fts ON fts.ID = p.ID
WHERE contains(fts.Name, '"White Dress"') 
ORDER BY p.DateMadeNew desc

Wenn Sie NHibernate verwenden mit / ohne Schloss Aktive Aufzeichnungen, ich habe in

Ein paar Gedanken über diese:

1) Haben Sie die Statistiken über die Produkttabelle aktualisiert? Es wäre sinnvoll, die Schätzungen und tatsächliche Anzahl der Zeilen auf den Operationen dort zu sehen.

2), welche Version von SQL Server verwenden Sie? Ich hatte ein ähnliches Problem mit SQL Server 2008, die nichts stellte sich heraus, mehr als nicht mit Service Pack 1 installiert sein. Installieren Sie SP1 und eine Freetext-Abfrage, die ein paar Minuten (aufgrund einer großen Anzahl von tatsächlichen Hinrichtungen gegen tatsächliche) ging auf unter eine Sekunde nahm.

scroll top