-1

クエリの実行に 1 分以上かかる
テーブルには 200 万行を超える
[sID] が PK
[textHash] にインデックスが付けられており、null が許可され
ている 両方のインデックスの断片化は 1% 未満です
私がしたいのは [textHash] の一致を追加することです[ textHash
] は null になる可能性があるため、2 つの結合条件が必要です

他の条件が構築される方法のため、メイン選択での結合はオプションではありません。
次のメジャー リリースでは、UNION を使用できるようにクエリの作成方法が変更されます。

一般に、null になる可能性のあるプロパティに参加したい null
の場合は、PK に基づいて行を含めます

Select top 10001 [docFam].[sID] 
From [docSVsys] with (nolock) 
LEFT OUTER JOIN [docSVsys] as [docFam] with (nolock) 
   On [docSVsys].[sID] = [docFam].[sID] 
   Or [docSVsys].[textHash] = [docFam].[textHash]
Where [docSVsys].[sID]  <=  '1000'
 Group By  [docFam].[sID] 
 Order By  [docFam].[sID] Asc 

クエリプランをコピーする方法を教えていただければ、含めます

HASH、MERGE、LOOP のヒントを試してみました。
最初の 2 つはコンパイラによって拒否され、LOOP は遅くなり、ヒントはありませんでした。

私は試した

On ([docSVsys].[textHash] is null and [docSVsys].[sID] = [docFam].[sID])
Or  [docSVsys].[textHash] = [docFam].[textHash]  

しかも遅かった

同様のクエリは 2 秒で実行されますが
、この場合 [sParID] は null ではないため、必要な結合条件は 1 つだけです

Select top 10001 [docFam].[sID] 
From [docSVsys] with (nolock) 
LEFT OUTER JOIN [docSVsys] as [docFam] with (nolock) 
   On [docSVsys].[sParID] = [docFam].[sParID] 
Where [docSVsys].[sID]  <=  '1000'
 Group By  [docFam].[sID] 
 Order By  [docFam].[sID] Asc

少数の行を返すクエリの場合、APPLY が機能します。
以下の構文は、上記の構文が 1 分かかるのに対し、1 秒で実行されます (1,022 行を返します)。

多くの行を返す条件の両方の形式のクエリにはまだ問題がありますが、それを SQL または構文の問題とは見なしていません。多くの行には時間がかかります。

Select [docFam].[sID] 
From [docSVsys] with (nolock)
OUTER APPLY -- cross apply 
  (   
    Select [docSVsysHashNull].[sID] 
    From   [docSVsys] as [docSVsysHashNull]with (nolock) 
    where  [docSVsysHashNull].[sID] = [docSVsys].[sID]
   union
    Select [docSVsysHashNotNull].[sID] 
    From   [docSVsys] as [docSVsysHashNotNull]with (nolock) 
    where  [docSVsysHashNotNull].[sID] != [docSVsys].[sID]
      and  [docSVsysHashNotNull].[textHash] = [docSVsys].[textHash]
  ) as docFam
Where [docSVsys].[sID]  <=  '1000'
Group By [docFam].[sID]
Order By [docFam].[sID] Asc
4

2 に答える 2

1

exists句を付けて書くことを検討しましたか。このようなもの

select distinct top 10001 a.[sID]
From [docSVsys] as a
where exists 
(
select *
From [docSVsys] as b
where b.[sID]<='1000'
and ( a.[sID] = b.[sID] OR a.[textHash] = b.[textHash])
)
于 2013-03-02T01:53:13.703 に答える
0

答えは@NikolaMarkovinovićからのコメントで提供されました

select distinct isnull(docFam.sID, docSVsys.sID) as sID 
from  docSVsys 
left  join docSVsys as docFam 
  on  docSVsys.textHash = docFam.textHash 
where ...
于 2013-03-04T17:22:56.637 に答える