これは私のクエリです:
With cte as (
Select
ROW_NUMBER() OVER (Order By d.OldInstrumentID ) peta_rn,
d.DocumentID
From Documents d
Inner Join Users u on d.UserID = u.UserID
Where 1=1
And (d.JurisdictionID = 1 Or DocumentStatusID = 5 Or DocumentStatusID = 9)
And d.DocumentStatusID <> 3 And d.DocumentStatusID <> 8
And d.DocumentStatusID <> 7
AND ((CreatedByJurisdictionID = 1 Or DocumentStatusID = 5 Or DocumentStatusID = 9 Or CreatedByAccountID IN (Select AccountID From AccountsJurisdictions Where JurisdictionID = 1)))
And d.DocumentStatusID = 9
)
Select
d.DocumentID,
d.IsReEfiled,
d.IGroupID,
d.ITypeID,
d.RecordingDateTime,
d.CreatedByAccountID,
d.JurisdictionID,
Case
When d.OldInstrumentID IS NULL
THEN d.LastStatusChangedDateTime
Else d.RecordingDateTime
End as LastStatusChangedDateTime,
dbo.FnCanChangeDocumentStatus(d.DocumentStatusID,d.DocumentID) as CanChangeStatus,
d.IDate,
d.InstrumentID,
d.DocumentStatusID,
d.DocumentDate,
Upper(dbo.GetFlatDocumentName(d.DocumentID)) as FlatDocumentName
From Documents d
Inner Join cte on cte.DocumentID = d.DocumentID
Where 1=1
And peta_rn>=80000
AND peta_rn<=80050
Order by peta_rn
DB には 100,000 件のレコードはほとんどありませんが、このクエリを実行して 50 件のレコードを取得するのに約 2 秒かかります。まったく受け入れられません!結合が使用されているほとんどの列にインデックスさえあります。
CTE の base 句で単一の結合が行われますが、これは必須です。結合がキラーであることは知っていますが、その1つの結合が必要です。これが次のコードを削除する場合:
And (d.JurisdictionID = 1 Or DocumentStatusID = 5 Or DocumentStatusID = 9)
And d.DocumentStatusID <> 3
And d.DocumentStatusID <> 8
And d.DocumentStatusID <> 7
AND ((CreatedByJurisdictionID = 1 Or DocumentStatusID = 5 Or DocumentStatusID = 9 Or CreatedByAccountID IN (Select AccountID From AccountsJurisdictions Where JurisdictionID = 1)))
And d.DocumentStatusID = 9
それは非常に速く実行されます。SSMS で 0 秒を表示します。このクエリを高速化する方法はありますか? それほど大きくないという条件が必要です。条件によってクエリの速度が低下するのはなぜですか? CreatedByAccountID およびその他の列には既にインデックスがあります。本当に忌々しい!
編集:
回答ありがとうございます。詳細:
あなたの多くは、冗長な条件を削除することを提案しました。申し訳ありませんが、この SQL はコードで動的に形成されており、そのバージョンを SSMS とここに貼り付けました。where句からこれらの条件を削除しても役に立たない:
Where 1=1
And (d.JurisdictionID = 1 Or d.DocumentStatusID = 5 Or d.DocumentStatusID = 9)
And d.DocumentStatusID <> 3
And d.DocumentStatusID <> 8
And d.DocumentStatusID <> 7
AND ((CreatedByJurisdictionID = 1 Or DocumentStatusID = 5 Or DocumentStatusID = 9 Or CreatedByAccountID IN (Select AccountID From AccountsJurisdictions Where JurisdictionID = 1)))
And d.DocumentStatusID = 9
実際のところ、where句を入れるとすぐに遅くなります。したがって、これでも遅いです:
Where 1=1
And (d.JurisdictionID = 1 Or d.DocumentStatusID = 5 Or d.DocumentStatusID = 9)
いくつかの詳細。Row_Number() の order by 句が決め手です。OldInstrumentID
type varchar(14) は遅く、2 秒かかりますがd.DocumentID
、int 型の which で注文すると、冗長な条件をすべて保持していても 0 秒で正常に動作します。
これは私の実行計画です:
アップデート:
各列にこのようなインデックスを作成しましたが、非常に高速に実行されるようです。ウーウー!!!
Create NonClustered Index IX_DocumentDate on Documents
(
DocumentDate
)
Include(
JurisdictionID,
JudgementTypeID,
IDate,
EfileDate,
UserID,
RecordingDateTime,
ApprovedBy,
ACEfileBankAccountID,
LastStatusChangedDateTime,
ACEfileCreditCardID,
EfiledByUserID,
ITypeID,
IGroupID,
InstrumentID,
OldInstrumentID,
[CreatedByJurisdictionID],
CreatedByAccountID,
[DocumentStatusID]
,[Remarks]
,[InternalNotes]
,[ParentDocumentID]
,[FilingNumber]
,[StampData]
,[Receipt]
,[ReceiptNo]
,[IsReEfiled]
,[ImportedFromInstrumentID]
)