web-dev-qa-db-ja.com

この非常に基本的なクエリでハッシュ一致演算子はなぜですか

実行プランを見て、クエリをより効率的にすることについて、いくつか学び始めています

次の2つの基本的なクエリを検討してください

select distinct pat_id, drug_class, drug_name from rx 

select pat_id, drug_class, drug_name from rx 

とその実行計画

enter image description here

使用されているインデックス:

CREATE CLUSTERED INDEX [ix_overlap] ON [dbo].[rx] 
(
    [pat_id] ASC,
    [fill_date] ASC,
    [script_end_date] ASC,
    [drug_name] ASC
)

最初のクエリは4:1のマージンでコストが高いと思われますが、2番目のクエリよりも高速に実行されます。クエリに追加された単純なDISTINCTが(常に悪いと想定しているものであり、修正は歓迎されます)ハッシュ一致演算子を追加するのはなぜですか?また、2番目のクエリの実行速度が速い場合、2番目のクエリと比べてクエリコストが高くなるのはなぜですか。

6

最初のクエリは並列プランを使用しています。つまり、「作業」は複数のスレッドによって実行される複数のタスクに分割されていました。したがって、累積CPU時間は、2番目のクエリに使用されるシリアルプランの場合よりも長くなりました。

なぜDISTINCTによってハッシュ一致演算子がプランに表示されるのかについて。 DISTINCTの結果を判別するには、集約またはソート操作が必要です。 @ SQLKiwi は、より詳細な説明がすぐに表示される可能性がありますが、ハッシュ一致演算子は、より大きな結果セットに適しているようです。

オプティマイザーは、ソートされた出力を生成する理由がなく、受信した行がDISTINCT式でソートされない、グループが少ない大きな行セットでハッシュ一致集約を優先する傾向があります。アルゴリズムは一般にスケーラビリティが高く(メモリの許可が必要ですが)、並列処理をうまく利用できるため、入力が大きいほどハッシュ照合が優先されます。ハッシュテーブルのエントリ数が少なくなるため、ハッシュに適したグループの数が少なくなり、一意の値を格納するために必要なメモリは、グループの数(およびグループのサイズ)に比例します。ハッシュマッチングでは、入力行ストリームの順序を必要とせず、維持する必要もありません。 [ソース]

6