SQL Server 2008 Standard で実行されている ETL コードがいくつかあります。比較的少数の行 (~50,000) が処理され、一時テーブルにロードされます。次に、挿入クエリを実行して、はるかに大きなテーブル (~1,000,000+ 行) に存在しない行をコピーします。一時テーブルには、宛先テーブルと同じ主キーとクラスター化インデックスが含まれています。
create table #NewClaims(ExtractDate datetime, SiteName nvarchar(50), SiteCd nvarchar(50), ContractTypeCd nvarchar(50),
ClaimRateType nvarchar(50), ClaimRateTypeCd nvarchar(50), ClaimStatus nvarchar(50), ClaimStatusCd nvarchar(50),
CreationDt datetime, StatusDt datetime, ClaimID nvarchar(50), SeqNum int, CreationUserID nvarchar(50),
SpecialClaimInd nvarchar(50), JobSeekerID nvarchar(50), InvoiceNum nvarchar(50), JobID nvarchar(50), JobRefId int,
RecoveryReason nvarchar(50), ClaimAmount money, GSTAmount money, ApprovedAmount money, ClaimCurrencyInd nvarchar(50),
EmployerID nvarchar(50), BaseRateType nvarchar(50), BaseRateTypeCd nvarchar(50)
constraint PK_NewClaims primary key clustered(ClaimID, ClaimStatusCD));
一時テーブルのレコードをターゲットにロードする SQL は次のとおりです。
insert into dbo.Claim(
ExtractDate, SiteName, SiteCd, ContractTypeCd, ClaimRateType, ClaimRateTypeCd, ClaimStatus, ClaimStatusCd, CreationDt,
StatusDt, ClaimID, SeqNum, CreationUserID, SpecialClaimInd, JobSeekerID, InvoiceNum, JobID, JobSeqNum, RecoveryReason,
ClaimAmount, GSTAmount, ApprovedAmount, ClaimCurrencyInd, EmployerID, BaseRateType, BaseRateTypeCd
)
select
n.ExtractDate, n.SiteName, n.SiteCd, n.ContractTypeCd, n.ClaimRateType, n.ClaimRateTypeCd, n.ClaimStatus, n.ClaimStatusCd,
n.CreationDt, n.StatusDt, n.ClaimID, n.SeqNum, n.CreationUserID, n.SpecialClaimInd, n.JobSeekerID, n.InvoiceNum, n.JobID,
n.JobRefId, n.RecoveryReason, n.ClaimAmount, n.GSTAmount, n.ApprovedAmount, n.ClaimCurrencyInd, n.EmployerID, n.BaseRateType,
n.BaseRateTypeCd
from #NewClaims as n
left join dbo.Claim as c on n.ClaimID = c.ClaimID and n.ClaimStatusCd = c.ClaimStatusCd
where c.ClaimID is null
これを実行すると、実行計画が異常な動作をします。dest テーブルで PK クラスター化インデックスを使用することを拒否し、代わりに利用可能な他のインデックスを使用しようとします。不思議なことに、このインデックスを使用して ClaimID と StatusCd を取得します。dest テーブルのインデックスを 1 つずつ無効にすると、クラスター化されたものを除くすべてのインデックスを無効にするまで、実行プランは他のインデックスを使用しようとし続けます。ビットマップ操作の。これが発生すると、クエリはより高速に実行されます。
また、インデックス ヒントを追加して実験しました: with (index(1))。このヒントにより、インデックスを使用して、ヒントのないバージョンよりもはるかに高速に動作し、期待どおりに動作します。強制インデックス シークにより、実行計画にスカラー演算子が表示されます - これは問題を示していますか?
Seek Keys[1]: Prefix: [ESD4].[dbo].[Claim].ClaimID, [ESD4].[dbo].[Claim].ClaimStatusCd = Scalar Operator([tempdb].[dbo].[#NewClaims].[ClaimID] as [n].[ClaimID]), Scalar Operator([tempdb].[dbo].[#NewClaims].[ClaimStatusCd] as [n].[ClaimStatusCd])
足りないものはありますか?インデックス ヒントはしばしば逆効果になる可能性があるため、SQL に特定の実行プランを強制的に使用させなければならないのは好きではありません。
アップデート
- テーブル統計の再計算は役に立ちませんでした
- 左結合から「存在しない場所」に変更しても、使用するインデックスの選択には影響しませんが、計画がわずかに変更されました。ハッシュ マッチ (Left Join) の代わりに、ハッシュ マッチ (Left Anti Semi Join) を実行するようになりました。これはおそらく高速です。