web-dev-qa-db-ja.com

ハッシュキープローブと残差

たとえば、次のようなクエリがあるとします。

_select a.*,b.*
from 
a join b
on a.col1=b.col1
and len(a.col1)=10
_

上記のクエリがハッシュ結合を使用し、残差があると仮定すると、プローブキーは_col1_になり、残差はlen(a.col1)=10になります。

しかし、別の例を検討していると、プローブと残差の両方が同じカラムであることがわかりました。以下は私が言おうとしていることの詳細です:

クエリ:

_select *
from T1 join T2 on T1.a = T2.a 
_

実行計画、プローブと残差が強調表示:

enter image description here

テストデータ:

_create table T1 (a int, b int, x char(200))
create table T2 (a int, b int, x char(200))

set nocount on
declare @i int
set @i = 0
while @i < 1000
  begin
      insert T1 values (@i * 2, @i * 5, @i)
    set @i = @i + 1
  end

declare @i int
set @i = 0
while @i < 10000
  begin
    insert T2 values (@i * 3, @i * 7, @i)
    set @i = @i + 1
  end
_

質問:

プローブと残差を同じカラムにするにはどうすればよいですか? SQL Serverがプローブ列のみを使用できないのはなぜですか?行を再度フィルタリングするために、同じ列を残差として使用する必要があるのはなぜですか?

テストデータの参照:

21
TheGameiswar

結合がtinyintsmallint、またはinteger *として入力された単一の列にあり、両方の列がNOT NULLに制約されている場合、ハッシュ関数は「完全」-ハッシュの衝突の可能性がないことを意味します。クエリプロセッサは、値が本当に一致することを確認するために値を再度チェックする必要はありません。

それ以外の場合、ハッシュバケット内のアイテムは、ハッシュ関数の一致だけでなく、一致についてテストされるため、残差が表示されます。

テストでは列にNULLまたはNOT NULLを指定していません(ところで、悪い習慣です)。したがって、NULLがデフォルトのデータベースを使用しているようです。

詳細については、投稿 Join Performance、Implicit Conversions、and Residuals and Hash Join Execution Internals by Dmitry Piluginを参照してください。


*他の修飾タイプはbitsmalldatetimesmallmoney、および(var)char(n)n = 1およびバイナリ照合

22
Paul White 9