2013-10-11 31 views
2

这是我的查询:即使我在IGroupes表上有索引,为什么还要进行表扫描?

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<[email protected] 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

任何帮助表示赞赏。谢谢!

+0

任何你无法将PK创建为簇的原因?这可能有所帮助,无论如何,这是一个好主意。 – usr

+0

@usr:我误将它删除了。谢谢!它现在显示聚簇索引扫描。我想转换它寻求。有什么办法吗? – Jack

+0

这很奇怪。在执行计划中,似乎在ID列上有一个简单的谓词。你可以用CI发布新计划吗? – usr

回答

2

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

主键PK_IGroupes上的索引应该被聚类。这将允许它进行索引查找(或书签查找)。如果由于某些其他原因无法进行聚类,请尝试按照IGroupIDAbbreviation的顺序(或在现有PK索引中包括Abbreviation列)创建索引。

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

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

2

可能在这种情况下,表扫描比使用IGroupes表中的任何索引更有效。 如果你认为表扫描操作是在此查询瓶颈(虽然3%的成本,我不知道这是),要么你可以尝试修改PK_IGroupes成为聚集索引或者,你可以尝试像

CREATE UNIQUE NONCLUSTERED INDEX [IX_IGroupes_IGroupID] 
    ON [dbo].[IGroupes] ([IGroupID]) INCLUDE ([Abbreviation]) 
+0

我试过这个解决方案,并使IGroupID作为群集。现在它显示聚簇索引扫描。我想转换它寻求。有什么办法吗? – Jack

+0

@Jack,扫描不一定意味着比寻找更糟糕的东西。例如,如果查询所有表或索引数据,扫描通常会出现而不是查找。 –

+0

我不能想出一种情况,即如果寻求密钥是可能的,CI扫描将优于CI查找。 – usr

相关问题