4

Productテーブルには700Kレコードが含まれています。クエリ:

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

実行には約1分かかります。DateMadeNewには非クラスター化インデックスがあり、NameにはFreeTextインデックスがあります。

TOP1またはOrderByを削除すると、実行に1秒もかかりません。

実行計画へのリンクは次のとおりです。 http://screencast.com/t/ZDczMzg5N

FullTextMatchには400Kを超える実行があるようです。なぜこうなった?どうすればもっと速くできますか?

2010年5月3日更新

カーディナリティは、複数単語のFreeText検索ではうまくいかないようです。

オプティマイザーは、「ホワイトドレス」に一致する28Kのレコードがあると推定していますが、実際には1つしかありません 。http://screencast.com/t/NjM3ZjE4NjAt

「白いドレス」を「白い」に置き換えると、推定数は「27,951」ですが、実際の数は「28,487」であり、はるかに優れています。

オプティマイザーは、カーディナリティを検索するフレーズの最初の単語のみを使用しているようです。

4

6 に答える 6

3

FullTextMatch の実行回数は 40 万回を超えているようです。なぜこうなった?

と組み合わせたインデックスがあるためTOP 1、オプティマイザーはインデックスをトラバースしてエントリの各レコードをチェックする方がよいと考えます。

どうすれば高速化できますか?

統計を更新しても解決しない場合は、クエリにヒントを追加してみてください。

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

これにより、エンジンはHASH JOINアルゴリズムを使用してテーブルとフルテキスト クエリの出力を結合するようになります。

KEY INDEXフルテキスト クエリは、定義で指定されたインデックス付きの値のセットを返すリモート ソースと見なされますFULLTEXT INDEX

アップデート:

ORMパラメーター化されたクエリを使用する場合は、プラン ガイドを作成できます。

  • Profiler を使用して、 が逐語的ORMに送信するクエリをインターセプトします。
  • SSMSヒントを使用して正しい計画を生成し、名前を付けて保存しますXML
  • とともに使用sp_create_plan_guideしてOPTION USE PLAN、オプティマイザが常にこの計画を使用するように強制します。
于 2010-04-30T17:52:09.737 に答える
1

リンクされた実行計画が表示されません。ネットワーク ポリスがブロックしているため、これは単なる推測です...

TOPandなしで高速に実行されている場合は、ORDER BYこれを試してください:

SELECT TOP 1
    *
    FROM (SELECT 
              ID, Name, DateMadeNew 
              FROM Product 
              WHERE contains(Name, '"White Dress"')
         ) dt
    ORDER BY DateMadeNew desc
于 2010-04-30T17:21:29.507 に答える
1

これに関するいくつかの考え:

1) Product テーブルの統計を更新しましたか? そこでも、操作の推定行数と実際の行数を確認すると便利です。

2) 使用している SQL Server のバージョンは何ですか? 私は SQL Server 2008 で同様の問題を抱えていましたが、それは Service Pack 1 がインストールされていないだけであることが判明しました。SP1 をインストールすると、数分かかっていた FreeText クエリ (実際の実行数に対して実際の実行数が非常に多いため) が 1 秒かかるようになりました。

于 2010-04-30T20:46:23.780 に答える
1

I have better solution.

I. Let's first overview proposed solutions as they also may be used in some cases:

  1. OPTION (HASH JOIN) - is not good as you may get error "Query processor could not produce a query plan because of the hints defined in this query. Resubmit the query without specifying any hints and without using SET FORCEPLAN."

  2. SELECT TOP 1 * FROM (ORIGINAL_SELECT) ORDER BY ... - is not good, when you need to use paginating results from you ORIGINAL_SELECT

  3. sp_create_plan_guide - is not good, as to use plan_guide you have to save plan for specific sql statement, this won't work for dynamic sql statements (e.g. generated by ORM)

II. My Solution contains of two parts 1. Self join table used for Full Text search 2. Use MS SQL HASH Join Hints MSDN Join Hints

Your SQL :

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

Should be rewritten as :

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

If you are using NHibernate with/without Castle Active Records, I've replied in post how to write interceptor to modify your query to replace INNER JOIN by INNER HASH JOIN

于 2010-12-30T09:13:52.513 に答える
1

編集

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

最も重要なことは、フルテキスト クエリに対して正しい結合タイプが選択されることです。FulltextMatch STVF でのカーディナリティの推定は、適切な計画にとって非常に重要です。したがって、最初に確認することは、FulltextMatch カーディナリティの推定です。これは、全文検索文字列のインデックス内の推定ヒット数です。たとえば、図 3 のクエリでは、これは用語「単語」を含むドキュメントの数に近いはずです。ほとんどの場合、それは非常に正確なはずですが、見積もりが大幅にずれていた場合、不適切な計画が作成される可能性があります。通常、単一項の推定は非常に良好です。ただし、語句や AND クエリなどの複数の用語の推定は、インデックス内の用語の頻度に基づいてインデックス内の用語の交差がどうなるかを知ることができないため、より複雑です。カーディナリティの見積もりが良好な場合、不適切な計画はおそらくクエリ オプティマイザーのコスト モデルが原因です。プランの問題を修正する唯一の方法は、クエリ ヒントを使用して、特定の種類の結合または OPTIMIZE FOR を強制することです。

そのため、2 つの検索用語がまったく独立している可能性が高いのか、それとも一般的に一緒に見つかる可能性が高いのかを、保存されている情報から知ることはできません。おそらく、オプティマイザーに処理を任せる単一ワード クエリ用と、「十分な」計画を強制する複数ワード プロシージャ用の 2 つの別個のプロシージャが必要です (sys.dm_fts_index_keywords が必要ない場合は、 1 つのサイズですべてのプランに適合します)。

注意: 記事のこの部分を見ると、単語プロシージャーに WITH RECOMPILE オプションが必要になる可能性があります。

SQL Server 2008 の全文検索では、使用された検索用語の基数推定に基づいて生成された計画を変更することができます。クエリ プランが固定されている場合 (ストアド プロシージャ内のパラメーター化されたクエリのように)、この手順は実行されません。したがって、このプランが特定の検索語にとって理想的でない場合でも、コンパイルされたプランは常にこのクエリを提供します。

元の回答

ただし、新しい計画はまだかなり悪いようです。全文クエリ パーツから 1 行しか返されていないように見えますが、Product テーブルの 770159 行すべてがスキャンされています。

これはどのように機能しますか?

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
于 2010-05-01T08:36:16.120 に答える
1

私は以前に同じ問題を抱えていました。

パフォーマンスは、フルテキスト インデックス作成に選択した一意のインデックスによって異なります。私のテーブルには、 と の 2 つの一意の列がIDありarticle_numberます。

クエリ:

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

全文索引が接続されているID場合、検索語によっては遅くなります。全文索引が索引に接続されている場合、ARTICLE_NUMBER UNIQUE常に高速でした。

于 2012-09-25T09:31:32.280 に答える