フリーテキストクエリは遅いです - トップと注文を含む
-
02-10-2019 - |
質問
製品テーブルには700kのレコードが含まれています。クエリ:
SELECT TOP 1 ID,
Name
FROM Product
WHERE contains(Name, '"White Dress"')
ORDER BY DateMadeNew desc
実行に約1分かかります。 datemadenewおよびfreeTextインデックスには、非クラスター化されたインデックスがあります。
トップ1または注文を削除すると、実行するには1秒以内です。
これが実行計画へのリンクです。http://screencast.com/t/zdczmzg5n
FullTextMatchには400K以上の実行があるようです。なぜこうなった?どのようにしてより速くすることができますか?
2010年5月3日更新
カーディナリティは、マルチワードフリーテキスト検索で強打されていないようです:
Optimizerは、「白いドレス」に一致する28Kのレコードがあると推定していますが、実際には1つしかありません。http://screencast.com/t/njm3zje4njat
「白いドレス」を「白」に置き換えると、推定数は「27、951」ですが、実際の数は「28、487」ですが、これははるかに優れています。
Optimizerは、カーディナリティを検索するフレーズの最初の単語のみを使用しているようです。
解決
編集
から http://technet.microsoft.com/en-us/library/cc721269.aspx#_toc202506240
最も重要なことは、正しい結合タイプがフルテキストクエリに選択されることです。 FullTextMatch STVFのカーディナリティの推定は、適切な計画にとって非常に重要です。したがって、最初に確認するのは、FullTextMatch Cardinalityの推定です。これは、フルテキスト検索文字列のインデックス内の推定ヒット数です。たとえば、図3のクエリでは、これは「単語」という用語を含むドキュメントの数に近い必要があります。ほとんどの場合、それは非常に正確でなければなりませんが、見積もりが長い間オフになった場合、悪い計画を生み出すことができます。単一用語の推定は通常非常に優れていますが、インデックス内の用語の交差点がインデックス内の用語の頻度に基づいていることを知ることができないため、フレーズやクエリなどの複数の用語を推定することはより複雑です。 。カーディナリティの推定が良好な場合、悪い計画はおそらくクエリオプティマイザーコストモデルによって引き起こされます。計画の問題を修正する唯一の方法は、クエリのヒントを使用して、特定の種類の結合または最適化を強制することです。
したがって、2つの検索用語が非常に独立している可能性があるか、一般的に一緒に見られるかどうかを保存する情報から単にわかりません。たぶん、Optimiserに「十分に良い」計画を強制するマルチワード手順で1つの単語クエリ用に1つの個別の手順がある必要があります(sys.dm_fts_index_keywordsが必要としない場合は役立つかもしれません1つのサイズがすべての計画に適合します)。
NB:単語の手順では、記事のこのビットを調べることで再コンパイルオプションが必要になる可能性があります。
SQL Server 2008フルテキスト検索では、使用された検索用語のカーディナリティ推定に基づいて生成される計画を変更する機能があります。クエリ計画が修正されている場合(ストアドプロシージャ内のパラメーター化されたクエリにあるため)、この手順は行われません。したがって、この計画が特定の検索用語に理想的ではない場合でも、コンパイルされた計画は常にこのクエリを提供します。
元の答え
あなたの新しい計画はまだかなり悪いように見えます。フルテキストクエリパーツから1行を返すだけでなく、製品テーブルのすべての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
他のヒント
私はリンクされた実行計画を見ることができません、ネットワーク警察はそれをブロックしているので、これは単なる推測です...
それがなくても速く実行されている場合 TOP
と ORDER BY
, 、これを試してみてください:
SELECT TOP 1
*
FROM (SELECT
ID, Name, DateMadeNew
FROM Product
WHERE contains(Name, '"White Dress"')
) dt
ORDER BY DateMadeNew desc
FullTextMatchには400K以上の実行があるようです。なぜこうなった?
インデックスが組み合わされているためです TOP 1
, 、Optimizerは、インデックスを通過する方が良いと考えており、エントリの各レコードを確認します。
どのようにしてより速くすることができますか?
統計を更新しても役に立たない場合は、クエリにヒントを追加してみてください。
SELECT TOP 1 *
FROM product pt
WHERE CONTAINS(name, '"test1"')
ORDER BY
datemadenew DESC
OPTION (HASH JOIN)
これにより、エンジンが使用されます HASH JOIN
テーブルに参加するアルゴリズムとフルテキストクエリの出力。
FullTextクエリは、索引付けされた値のセットを返すリモートソースと見なされます KEY INDEX
で提供されます FULLTEXT INDEX
意味。
アップデート:
もしあなたの ORM
パラメーター化されたクエリを使用すると、プランガイドを作成できます。
- プロファイラーを使用して、次のクエリを傍受します
ORM
送信 逐語的 - 正しい計画を生成します
SSMS
ヒントを使用して、それを保存しますXML
- 使用する
sp_create_plan_guide
でOPTION USE PLAN
オプティマイザーを強制するには、常にこの計画を使用してください。
以前も同じ問題がありました。
パフォーマンスは、フルテキストインデックスにどの一意のインデックスを選択するかによって異なります。私のテーブルには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
インデックスは常に高速でした。
私はより良い解決策を持っています。
I.最初に提案されたソリューションは、場合によっては使用される可能性があるため、最初に提案されたソリューションを概要しましょう。
オプション(ハッシュ参加) - エラーが発生する可能性があるため良くありません 「クエリプロセッサは、このクエリで定義されているヒントのためにクエリプランを作成できませんでした。ヒントを指定せずに、Set ForcePlanを使用せずにクエリを再送信します。」
選択結果を使用する必要がある場合は、トップ1 * from(Original_Select)Orderを選択してください。
SP_CREATE_PLAN_GUIDE-特定のSQLステートメントのプランを保存する必要があるため、Plan_Guideを使用するためには良くありません。これは、動的SQLステートメント(ORMによって生成された例)では機能しません。
ii。私のソリューションには2つの部分が含まれています1.フルテキスト検索に使用されるセルフ結合テーブル2. MS SQLハッシュを使用するヒント。 MSDNがヒントに参加します
あなたのSQL:
SELECT TOP 1 ID, Name FROM Product WHERE contains(Name, '"White Dress"')
ORDER BY DateMadeNew desc
次のように書き直す必要があります。
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
キャッスルアクティブレコードの有無にかかわらずnhibernateを使用している場合、私は返信しました 役職 インターセプターを書き込む方法クエリを変更して、内側のハッシュ結合で内部結合を置き換える
これについてのいくつかの考え:
1)製品テーブルの統計を更新しましたか?操作の推定値と実際の行数も表示すると便利です。
2)どのバージョンのSQL Serverを使用していますか? SQL Server 2008にも同様の問題がありましたが、サービスパック1をインストールしていないことが判明しました。 SP1と数分かかっていたフリーテキストクエリをインストールしました(実際の実際の数の実際の実行により)1秒かかりました。