2

これは私のクエリです:

exec sp_executesql N'set arithabort off;set statistics time on; set transaction isolation level read uncommitted;With cte as (Select peta_rn = ROW_NUMBER() OVER (ORDER BY  d.LastStatusChangedDateTime  desc )  
                                                , d.DocumentID,
                                                d.IsReEfiled, d.IGroupID, d.ITypeID, d.RecordingDateTime, d.CreatedByAccountID, d.JurisdictionID, 
                                                d.LastStatusChangedDateTime as LastStatusChangedDateTime
                                                ,  d.IDate, d.InstrumentID, d.DocumentStatusID
                                                , u.Username
                                                , it.Abbreviation AS ITypeAbbreviation
                                                , ig.Abbreviation AS IGroupAbbreviation,
                                                d.DocumentDate                                               
                                From Documents d                             
                                Inner Join ITypes it  on it.ITypeID = d.ITypeID
                                 Inner Join Users u on d.UserID = u.UserID Inner Join IGroupes ig on ig.IGroupID = d.IGroupID
                                Where 1=1  And  (  d.DocumentStatusID = 9  ) ) Select cte.DocumentID, 
                                cte.IsReEfiled, cte.IGroupID, cte.ITypeID, cte.RecordingDateTime, cte.CreatedByAccountID, cte.JurisdictionID, 
                        cte.LastStatusChangedDateTime as LastStatusChangedDateTime
                        ,  cte.IDate, cte.InstrumentID, cte.DocumentStatusID,cte.IGroupAbbreviation, cte.Username, j.JDAbbreviation, inf.DocumentName,
                       cte.ITypeAbbreviation, cte.DocumentDate, ds.Abbreviation as DocumentStatusAbbreviation,  ds.Name as DocumentStatusName,
                        ( SELECT CAST(CASE WHEN cte.DocumentID = (
                                SELECT TOP 1 doc.DocumentID
                                FROM  Documents doc
                                WHERE doc.JurisdictionID = cte.JurisdictionID
                                        AND doc.DocumentStatusID = cte.DocumentStatusID
                                ORDER BY LastStatusChangedDateTime) 
                            THEN 1
                            ELSE 0
                        END AS BIT)
                        ) AS CanChangeStatus ,

                        Upper((Select Top 1 Stuff( (Select ''='' + dbo.GetDocumentNameFromParamsWithPartyType(Business, FirstName, MiddleName, LastName, t.Abbreviation, NameTypeID, pt.Abbreviation, IsGrantor, IsGrantee)  From DocumentNames dn
                                Left Join Titles t
                                    on dn.TitleID = t.TitleID               
                                Left Join PartyTypes pt
                                    On pt.PartyTypeID = dn.PartyTypeID
                                        Where DocumentID = cte.DocumentID
                                            For XML PATH('''')),1,1,''''))) as FlatDocumentName, (SELECT COUNT(*) FROM CTE) AS TotalRecords

                        FROM cte Left Join DocumentStatuses ds On
                        cte.DocumentStatusID = ds.DocumentStatusID Left Join InstrumentFiles inf On cte.DocumentID = inf.DocumentID 
                    Left Join Jurisdictions j on j.JurisdictionID = cte.JurisdictionID Where 1=1 And 
                    peta_rn>@7 AND peta_rn<=@8 Order by peta_rn set statistics time off; ',N'@0 int,@1 int,@2 int,@3 int,@4 int,@5 int,@6 int,@7 int,@8 int',
                    @0=1,@1=5,@2=9,@3=1,@4=5,@5=9,@6=1,@7=97500,@8=97550

そして、これは私の IGroupes テーブル定義です:

CREATE TABLE [dbo].[IGroupes](
    [IGroupID] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](64) NOT NULL,
    [JurisdictionID] [int] NOT NULL,
    [Abbreviation] [varchar](12) NOT NULL,
 CONSTRAINT [PK_IGroupes] PRIMARY KEY NONCLUSTERED 
(
    [IGroupID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

SET ANSI_PADDING ON

GO

/****** Object:  Index [IX_IGroupes_Abbreviation]    Script Date: 10/11/2013 4:21:46 AM ******/
CREATE NONCLUSTERED INDEX [IX_IGroupes_Abbreviation] ON [dbo].[IGroupes]
(
    [Abbreviation] ASC
)
INCLUDE (   [IGroupID],
    [Name],
    [JurisdictionID]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
GO

SET ANSI_PADDING ON

GO

/****** Object:  Index [IX_IGroupes_JurisdictionID]    Script Date: 10/11/2013 4:21:46 AM ******/
CREATE NONCLUSTERED INDEX [IX_IGroupes_JurisdictionID] ON [dbo].[IGroupes]
(
    [JurisdictionID] ASC
)
INCLUDE (   [IGroupID],
    [Name],
    [Abbreviation]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
GO

SET ANSI_PADDING ON

GO

/****** Object:  Index [IX_IGroupes_Name]    Script Date: 10/11/2013 4:21:46 AM ******/
CREATE NONCLUSTERED INDEX [IX_IGroupes_Name] ON [dbo].[IGroupes]
(
    [Name] ASC
)
INCLUDE (   [IGroupID],
    [JurisdictionID],
    [Abbreviation]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
GO

ただし、テーブルスキャンを使用していることを確認してください。この操作にはコストがかかりすぎます。IGroupesテーブルには 7 行しかなく、Documentsテーブルには約 98K のレコードがあります。しかし、参加するd.IGroupID = ig.IGroupIDと、実際の行数が 600K を超えています! それが問題だ。添付のスクリーンショットをご覧ください。

ここに画像の説明を入力

完全なクエリ プラン xml に興味がある場合は、次のとおりです。

https://www.dropbox.com/s/kldx24x3j8vndpe/plan.xml

どんな助けでも大歓迎です。ありがとう!

4

2 に答える 2

2

おそらくこの場合、テーブルスキャンは、テーブルにあるインデックスを使用するよりも効率的ですIGroupes。このクエリでテーブル スキャン操作がボトルネックであると思われる場合 (コストが 3% であることはわかりませんが)、PK_IGroupesクラスター化インデックスになるように変更するか、次のようなインデックスを試すことができます。

CREATE UNIQUE NONCLUSTERED INDEX [IX_IGroupes_IGroupID]
    ON [dbo].[IGroupes] ([IGroupID]) INCLUDE ([Abbreviation])
于 2013-10-11T09:43:24.757 に答える
2

IGroupeswhere または join 句でこれらのフィールドを使用していないため、使用している 3 つのインデックス (PK 以外) はいずれもこのクエリに役立ちません。他のクエリでこれらのインデックスが必要でない限り、削除します。それらは、クエリ オプティマイザーにテスト (および拒否) するためのより多くの選択肢を与えるだけです。

主キーのインデックスはPK_IGroupesクラスター化する必要があります。これにより、インデックス シーク (またはブックマーク ルックアップ) を行うことができます。他の理由でクラスター化できない場合は、 と のインデックスをこの順序で作成してみてくださいIGroupID(AbbreviationまたはAbbreviation、既存の PK インデックスに列を含めます)。

それでも正しいインデックスが取得されない場合は、WITH(INDEX(0))またはなどのヒントを使用できますWITH(INDEX('index-name'))

600k 行は、7 行を掛けた 98k 行でネストされたループ結合を実行しているという事実から来ています。上記のインデックスが機能しない場合は、 を に置き換えてみてINNER JOIN iGroupesくださいINNER HASH JOIN IGroupes

于 2013-10-11T16:12:03.370 に答える