RPM*_*984 16 t-sql indexing performance sql-server-2008 sql-execution-plan
这是查询:
SELECT top 100 a.LocationId, b.SearchQuery, b.SearchRank
FROM dbo.Locations a
INNER JOIN dbo.LocationCache b ON a.LocationId = b.LocationId
WHERE a.CountryId = 2
AND a.Type = 7
Run Code Online (Sandbox Code Playgroud)
位置索引:
PK_Locations:
LocationId
IX_Locations_CountryId_Type:
CountryId,Type
LocationCache索引:
PK_LocationCache:
LocationId
IX_LocationCache_LocationId_SearchQuery_SearchRank:
LocationId,SearchQuery,SearchRank
执行计划:

所以它正在使用覆盖索引做一个关于位置的索引搜索,很酷.
但是为什么它在LocationCache覆盖索引上进行索引扫描?
覆盖索引在索引中具有LocationId,SearchQuery,SearchRank(而不是"包含的列").
将鼠标悬停在索引扫描上:

此查询需要进入由自动完成插件使用的SQL Server FTS目录提供的索引视图,因此需要100%优化.
目前,上述查询需要3秒钟.它应该<0.
有任何想法吗?
RBa*_*ung 33
它主要使用索引扫描,因为它也使用合并连接.Merge Join运算符需要两个输入流,这两个输入流都按照与Join条件兼容的顺序排序.
它正在使用Merge Join运算符来实现INNER JOIN,因为它相信它会比更典型的Nested Loop Join运算符更快.并且它可能是正确的(通常是),通过使用它选择的两个索引,它具有根据您的连接条件(LocationID)预先排序的输入流.当输入流像这样预先排序时,Merge Joins几乎总是比其他两个(Loop和Hash Joins)更快.
缺点是你已经注意到了:它似乎是在扫描整个索引,所以如果读取那么多可能永远不会被使用的记录,那怎么会更快呢?答案是,扫描(因为它们的顺序性质)可以读取任何数量的记录/秒的10到100倍.
现在寻求通常赢,因为它们是有选择性的:它们只获得你要求的行,而扫描是非选择性的:它们必须返回范围内的每一行.但由于扫描有很多更高的读取速度,他们可以经常击败只要废弃行来匹配行的比例为寻求更低比扫描行/秒VS的比 寻求行/秒.
有问题吗?
好的,我被要求更多地解释最后一句话:
"Discarded Row"是Scan读取的一个(因为它必须读取索引中的所有内容),但是Merge Join操作符会拒绝它,因为它在另一侧没有匹配,可能是因为WHERE子句条件已经排除它.
"匹配行"是它读取的实际上与Merge Join中的某些内容匹配的行.如果扫描被Seek替换,这些行将被Seek读取.
您可以通过查看查询计划中的统计信息来确定存在的内容.看到Index Scan左侧那个巨大的胖箭头?这表示优化器认为它将使用Scan读取的行数.您发布的索引扫描的统计信息框显示返回的实际行数约为5.4M(5,394,402).这相当于:
TotalScanRows = (MatchingRows + DiscardedRows)
Run Code Online (Sandbox Code Playgroud)
(就我而言,无论如何).要获得匹配行,请查看Merge Join运算符报告的"实际行"(您可能必须取下TOP 100才能准确地获得此值).一旦你知道这一点,你可以通过以下方式获得Discarded行:
DiscardedRows = (TotalScanRows - MatchingRows)
Run Code Online (Sandbox Code Playgroud)
现在你可以计算比率了.
同时请记住,当对其进行其他更改时,它将导致查询可能执行得很糟糕,使用INNER LOOP JOIN应强制使用覆盖索引dbo.LocationCache.
SELECT top 100 a.LocationId, b.SearchQuery, b.SearchRank
FROM dbo.Locations a
INNER LOOP JOIN dbo.LocationCache b ON a.LocationId = b.LocationId
WHERE a.CountryId = 2
AND a.Type = 7
Run Code Online (Sandbox Code Playgroud)