ページ編集時にSQL Serverクエリが遅い


14

SQL Server 2012では、次のT-SQLクエリで奇妙な動作が見られます。

SELECT Id 
FROM dbo.Person 
WHERE CONTAINS(Name, '"John" AND "Smith"')
ORDER BY Name

このクエリを単独で実行すると、2秒未満で約1,300の結果が得られます(フルテキストインデックスがありますName)。

ただし、クエリをこれに変更すると:

SELECT Id 
FROM dbo.Person 
WHERE CONTAINS(Name, '"John" AND "Smith"')
ORDER BY Name
OFFSET 0 rows
FETCH NEXT 10 ROWS ONLY

10件の結果を得るには20秒以上かかります。

次のクエリはさらに悪いです。

SELECT Id 
FROM ( 
    SELECT ROW_NUMBER() OVER (ORDER BY Name) AS RowNum, Id 
    FROM dbo.Person
    WHERE CONTAINS(Name, '"John" AND "Smith"') ) AS RowConstrainedResult 
WHERE RowNum >= 0 AND RowNum < 11 
ORDER BY RowNum

完了するには1.5分以上かかります!

何か案は?

スロープラン

スロー

高速計画

速い


2番目のクエリをに変更するとどうなりますSELECT TOP 10 * .... ORDER BY Nameか?
ラマク

インデックスIX_PersonSearch ...はどの列で作成されますか?テーブルから*を選択しており、使用されているインデックスにすべての出力列が含まれていないため、キールックアップを取得しています。必要な列のみを選択し、インデックス列ではなく、含まれる列として非クラスター化インデックスに含める必要があると思います。
マルセルN.

テーブルにインデックスを投稿できますか(スクリプトを作成します)?

3
IDは常にすべての非クラスター化インデックスに含まれます。これは、SQL Serverが(IDによる)検索をキー設定できる方法です。
usr

1
私が言及するのを忘れていたのは、CONTAINSではなくLIKEで同じクエリを実行すると、高速です。(ページ分割されているかどうか)

回答:


7

TOP 10名前順に並べたいだけなので、インデックスをname順番に調べて、各行がCONTAINS(Name, '"John" AND "Smith"') )述語と一致するかどうかを確認する方が速いと考えています。

おそらく、必要な10の一致を見つけるためにさらに多くの行が必要であり、このカーディナリティの問題は、キールックアップの数によってさらに悪化します。

この計画を使用してそれを停止する簡単なハックは、に変更するORDER BYことですORDER BY Name + ''ますがCONTAINSTABLE、と組み合わせて使用することFORCE ORDERもできます。


3

これは、古典的な選択性の推定のように見えます。クエリの「ドライバー」は全文検索であり、統計情報で拡張できないため、何ができるかわかりません。

where contains述語を書き換えてみてくださいinner join containstableCONTAINSTABLE)に結合順序のヒントを適用して計画の形状を強制します。

メンテナンスの問題があるため、これは完璧なソリューションではありませんが、別の方法がわかりません。


あなたの答えをありがとう、私はそれを試しました。同じ結果:ページネーションを使用しない場合、クエリは非常に高速です。ページネーションが突然再び遅くなります:/

計画を画像とクエリとして投稿できますか?望みの形状を生成するのにまだ成功していないと思います。
usr

3

私は問題を解決することができました:

質問で私が言ったように、すべての列に指標があり、各列の統計がありました。(従来のLIKEクエリのため)すべてのインデックスと統計を削除し、全文検索とボイラを追加して、クエリが非常に高速になりました。

インディゼーションは異なる実行計画につながったようです。

ご協力ありがとうございました!


1
インデックスを完全に削除することは、インデックスが使用されないようにする1つの方法です。
マーティンスミス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.