9

可能性のある説明は、SQL Server 2014 Enterprise Edition(64ビット)で、ここでin the commentSQL Serverクエリ最適化 - 単純なクエリで予期しない遅さ

である - 私は、ビューから読み取るしようとしています。標準クエリには、このようにORDER BYOFFSET-FETCH句が含まれています。

アプローチ1

SELECT 

    * 

FROM Metadata 
ORDER BY 
    AgeInHours  ASC, 
    RankingPoint DESC, 
    PublishDate  DESC 
OFFSET 150000 ROWS 
FETCH NEXT 40 ROWS ONLY 

しかし、この非常に単純なクエリは、同じ結果を返す次のクエリよりも(顕著150Kのような多数の行をスキップする)ほぼ9倍遅い行います。私は主キーを最初に読み取り、次いでWHERE...IN機能

アプローチ2

SELECT 
    * 
FROM Metadata 
WHERE NewsId IN (
    SELECT 

     NewsId 

    FROM Metadata 
    ORDER BY 
     AgeInHours  ASC, 
     RankingPoint DESC, 
     PublishDate  DESC 
    OFFSET 150000 ROWS 
    FETCH NEXT 40 ROWS ONLY 
) 
ORDER BY 
    AgeInHours  ASC, 
    RankingPoint DESC, 
    PublishDate  DESC 

ベンチマーキング、これら2つのショーこの差

のパラメータとしてそれを使用しています。この場合

(40 row(s) affected) 

SQL Server Execution Times: 
    CPU time = 14748 ms, elapsed time = 3329 ms. 

(40 row(s) affected) 

SQL Server Execution Times: 
    CPU time = 3828 ms, elapsed time = 469 ms. 

私はプライマリキーのインデックスがPubilshDateで、そのフラグメントはイオンは非常に低いです。私もデータベーステーブルに対して同様のクエリを実行しようとしましたが、すべてのケースで2番目のアプローチは大きなパフォーマンス向上をもたらします。また、SQL Server 2012でこれをテストしました。

何が起こっているのか説明できますか?

スキーマ

Schema

アプローチ1:実行計画

Approach 1: Execution Plan

アプローチ2:実行プラン(左部分)

Approach 2: Execution Plan (Left part)

アプローチ2:実行計画(右部分)

Approach 2: Execution Plan (Right part)

+0

最初のアプローチを実行して** ** IDのみの列を選択すると、どうなりますか? '*'アスタリスクは、列全体を強制的にスキャンするので、アスタリスクはクエリの速度を遅くするものと思われます。 – sagi

+0

インデックス化された列( 'Id')のみを検索するよりもずっと高速です(ほとんど9回、言います)。困ったことは、2番目のクエリでは、WHERE-IN句を使用しても同じ量のデータを読み込んでいますが、時間はかかりません。シーンの後ろで何が起こっていますか? – undefined

+3

クエリプランとテーブルスキーマを含めることはできますか? –

答えて

0

あなたはエンジンが最高のパフォーマンスを得るために使用することができ、インデックスのためのルックアップクエリを実行すると。あなたのアプローチ1はSELECTステートメントのすべての列を含まないインデックスを使用しています。これはクエリプランのキールックアップを引き起こします。私の経験では、SELECTステートメントのインデックス付き列のみを使用するパフォーマンスが常に低下します。

AgeInHours, RankingPoint, PublishDateのインデックスを作成し、すべての列をINCLUDE(テスト目的のみに推奨)すると、その違いがわかります。

CTEを使用している場合は、さらにパフォーマンスが向上し、INでWHEREを使用する代わりにJOINを作成したり、数百万行がある場合はインデックス付きのテンポラリテーブルを作成したりすることもできます。

1

同じ結果セットでも異なる構造化クエリの場合、異なるアプローチとクエリコストで異なるクエリプランが得られます。これは、さまざまなSQL RDBMS実装に共通しています。

基本的に上記のサンプルでは、​​大きなテーブルから小さなデータを選択すると、最初に結果の行数を減らして最小限に抑え、2つのクエリのようにすべての列を含む完全な行を選択するのがよい方法です。

もう1つの方法は、最初のステップで結果セットを減らすための正確な適切なインデックスを作成することです。上記のクエリでは、ORDER BY句の列が同じ列と並べ替え順である可能性があります。

(あなたは私はちょうど彼らの名前の後ろに隠れているものを想像することができるクエリ計画に言及したインデックスの構造を送っていませんでした。)

また、あなたは考える特定のインデックスへの直接SQLオプティマイザにヒンティングSQLインデックスを使用することができますSQLオプティマイザがその仕事をしない場合のタスクにとって最適です。