Sql server 为什么即使我在IGroupes表上有索引,也要进行表扫描?
这是我的疑问:Sql server 为什么即使我在IGroupes表上有索引,也要进行表扫描?,sql-server,tsql,sql-server-2012,rdbms,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 )
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
但请看它使用的是表扫描。这次手术花了我太多钱i组
表只有7行,而文档
表大约有98K条记录。然而,当我在d.IGroupID=ig.IGroupID
上加入时,它显示了超过600K的实际行数!这就是问题所在。请参见随附的屏幕截图:
如果有人对完整的查询计划xml感兴趣,请参见:
感谢您的帮助。谢谢 在这种情况下,表扫描可能比使用
i组
表上的任何索引更有效。
如果您认为表扫描操作是此查询中的瓶颈(尽管成本为3%,我不确定是否是),您可以尝试将PK\u igroups
修改为聚集索引,也可以尝试类似索引的操作
CREATE UNIQUE NONCLUSTERED INDEX [IX_IGroupes_IGroupID]
ON [dbo].[IGroupes] ([IGroupID]) INCLUDE ([Abbreviation])
在这种情况下,表扫描可能比使用
igroups
表上的任何索引更有效。
如果您认为表扫描操作是此查询中的瓶颈(尽管成本为3%,我不确定是否是),您可以尝试将PK\u igroups
修改为聚集索引,也可以尝试类似索引的操作
CREATE UNIQUE NONCLUSTERED INDEX [IX_IGroupes_IGroupID]
ON [dbo].[IGroupes] ([IGroupID]) INCLUDE ([Abbreviation])
您在igroups
上拥有的3个索引(PK除外)都不能帮助此查询,因为您没有在where或join子句中使用这些字段。除非其他查询需要这些索引,否则我将删除它们。他们只是给查询优化器更多的选择来测试(和拒绝)
主键PK_igroups
上的索引应进行聚类。这将允许它进行索引查找(或书签查找)。如果由于其他原因无法对其进行聚集,请尝试按顺序在IGroupID
和缩写
上创建索引(或在现有PK索引中包含缩写
列)
如果它仍然没有选择正确的索引,您可以使用提示,例如WITH(index(0))
或WITH(index('index-name'))
600k行确实来自这样一个事实,即它在98k行上进行嵌套循环联接,并乘以7行。如果上面的索引不起作用,您可以尝试用内部哈希连接iGroupes
替换内部连接iGroupes
替换iGroupes
上的3个索引(PK除外)都无法帮助此查询,因为您没有在where或JOIN子句中使用这些字段。除非其他查询需要这些索引,否则我将删除它们。他们只是给查询优化器更多的选择来测试(和拒绝)
主键PK_igroups
上的索引应进行聚类。这将允许它进行索引查找(或书签查找)。如果由于其他原因无法对其进行聚集,请尝试按顺序在IGroupID
和缩写
上创建索引(或在现有PK索引中包含缩写
列)
如果它仍然没有选择正确的索引,您可以使用提示,例如WITH(index(0))
或WITH(index('index-name'))
600k行确实来自这样一个事实,即它在98k行上进行嵌套循环联接,并乘以7行。如果上面的索引不起作用,您可以尝试用
内部哈希连接iGroupes
替换内部连接iGroupes
来替换内部连接iGroupes您为什么不能将PK创建为集群?这可能会有帮助,而且是个好主意。@usr:我错把它删除了。谢谢现在显示聚集索引扫描。我想把它转换成seek。有什么办法吗?真奇怪。在执行计划中,ID列上似乎有一个简单的谓词。你能用CI发布新计划吗?你有更新的统计数据吗?您是否尝试将加入到IGroups的活动移出CTE?usr:感谢您的帮助。这是一个新的计划:你为什么不能将PK创建为集群?这可能会有帮助,而且是个好主意。@usr:我错把它删除了。谢谢现在显示聚集索引扫描。我想把它转换成seek。有什么办法吗?真奇怪。在执行计划中,ID列上似乎有一个简单的谓词。你能用CI发布新计划吗?你有更新的统计数据吗?您是否尝试将加入到IGroups的活动移出CTE?usr:感谢您的帮助。下面是新的计划:我尝试了这个解决方案,并将IGroupID设置为集群。现在显示聚集索引扫描。我想把它转换成seek。“有什么办法吗?”杰克,扫描不一定意味着比搜索更糟糕的事情。例如,如果查询所有表或索引数据,则扫描经常出现,而不是搜索。如果可以在键上搜索,我想不出CI扫描比CI搜索更可取的情况。@I-phone:我理解,但我只是查询缩写,它已经包含在NCI中了定义。@i-phone:我只担心这个问题,因为如果我不加入igroups(一个7行的小表),我的查询速度几乎降低了一半,因为你可以看到实际行数超过600K,我完全无法理解为什么会发生这种情况。这是一个包含7行的简单查找表,它使我的查询速度加倍:(.如果我不加入iGroup,我将在300毫秒内在100K记录表中返回结果,如果加入,我将在700毫秒内返回结果。对于查找表来说,这是一个相当大的差异:(我尝试了这个解决方案,并将IGroupID设置为聚集。现在它显示聚集索引扫描。我想将其转换为seek。有什么办法吗?@Jack,scan不一定意味着比seek更糟糕的事情。例如,如果查询所有表或索引数据,则扫描经常出现,而不是seek。我无法想出CI出现的情况如果可以在键上搜索,则扫描比CI搜索更可取。@i-phone:我理解,但我只是查询缩写,它已经在i中了