即使我在IGroupes表上有索引,为什么还有表扫描?

时间:2013-10-11 08:27:32

标签: sql-server tsql sql-server-2012 rdbms

这是我的疑问:

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的实际行数!那就是问题所在。请参阅随附的屏幕截图:

enter image description here

如果有人对完整的查询计划xml感兴趣,那么它是:

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

感谢任何帮助。谢谢!

2 个答案:

答案 0 :(得分:2)

在这种情况下,表扫描可能比使用IGroupes表上的任何索引更有效。 如果您认为表扫描操作是此查询的瓶颈(虽然成本为3%,我不确定),您可以尝试修改PK_IGroupes成为聚簇索引,也可以尝试像

这样的索引
CREATE UNIQUE NONCLUSTERED INDEX [IX_IGroupes_IGroupID]
    ON [dbo].[IGroupes] ([IGroupID]) INCLUDE ([Abbreviation])

答案 1 :(得分:2)

IGroupes上的3个索引(PK除外)都没有帮助此查询,因为您没有在where或join子句中使用任何这些字段。除非您需要其他查询的索引,否则我会删除它们。它们只是为查询优化器提供了更多的选择来测试(和拒绝)。

主键PK_IGroupes上的索引应该是群集的。这将允许它进行索引搜索(或书签查找)。如果由于其他原因无法对其进行群集,请尝试按此顺序在IGroupIDAbbreviation上创建索引(或在现有PK索引中包含Abbreviation列)。< / p>

如果它仍然没有选择正确的索引,您可以使用WITH(INDEX(0))WITH(INDEX('index-name'))等提示。

600k行的确来自于它在98k行上乘以7行进行嵌套循环连接。如果上述索引不起作用,您可以尝试将INNER JOIN iGroupes替换为INNER HASH JOIN IGroupes