sql 键查找 索引查找
抽象 (Abstract)
It is common assumption that an Index Seek operation in a query plan is optimal when returning a low number of output rows. In a scenario involving residual predicates, an Index Seek operation could be reading a lot more rows than it needs into the memory, then each row is evaluated and discarded in memory based on the residual predicate and returns low number of output rows.
通常假设在返回少量输出行时查询计划中的索引查找操作是最佳的。 在涉及残留谓词的场景中,索引查找操作可能会向内存中读取比其所需数量更多的行,然后,根据残留谓词对每一行进行评估并丢弃到内存中,并返回少量的输出行。
This article will explain the concept and the impact of Residual Predicates in a SQL Server Index Seek operation.
本文将解释SQL Server索引查找操作中残留谓词的概念和影响。
索引搜寻操作 (Index Seek Operation)
SQL Server accesses a table or an index via the mean of a lookup, scan or a seek operation. In an index seek operation, a Seek Predicate is when SQL Server is able to get the exact filtered result. In the case of an index seek on multi-column, SQL Server may introduce a Predicate in the Index Seek operation. This Predicate is often referred as residual predicate because SQL Server performs additional filtering on the resultset from the index seek operation.
SQL Server通过查找,扫描或查找操作的方式访问表或索引。 在索引查找操作中,“查找谓词”是指SQL Server能够获得准确的筛选结果。 在多列上进行索引查找的情况下,SQL Server可能在索引查找操作中引入谓词。 该谓词通常称为残差谓词,因为SQL Server对来自索引查找操作的结果集执行附加筛选。
To understand the behaviour of residual predicate in SQL Server, we will walk-through two scenarios
若要了解残留谓词在SQL Server中的行为,我们将演练两种情况
- Index Seek 索引搜寻
- Index Seek with Residual Predicate 带有谓词的索引搜索
The scenarios will utilize WideWorldImportersDW database on SQL Server 2016 Developer Edition Service Pack 1.
这些方案将利用SQL Server 2016 Developer Edition Service Pack 1上的WideWorldImportersDW数据库。
索引搜寻谓词 (Index Seek Predicate)
This scenario will walkthrough a common index seek predicate operation. First, we will create a non-clustered index on [Fact].[Order] table as below
此场景将演练通用索引查找谓词操作。 首先,我们将在[Fact]。[Order]表上创建一个非聚集索引,如下所示
USE WideWorldImportersDW
GO
CREATE NONCLUSTERED INDEX IX_SQLShack_StockItemKey ON [Fact].[Order] ([Salesperson Key])
INCLUDE ([Stock Item Key])
We will now execute the query below and look at the query plan and the I/O statistics
现在,我们将在下面执行查询,并查看查询计划和I / O统计信息
A total of 2,585 rows returned and the logical reads incurred are 22 reads.
总共返回了2585行,并且发生的逻辑读取是22次读取。
We need to pay attention to a new SQL Server XML attribute Number of Rows Read in the query plan which was introduced in the SQL Server Service Pack level listed below to diagnose query plan which involved predicate pushdown.
我们需要注意查询计划中新SQL Server XML属性“已读取行数” ,该属性在下面列出SQL Server Service Pack级别中引入,用于诊断涉及谓词下推的查询计划。
- SQL Server 2012 Service Pack 3 SQL Server 2012 Service Pack 3
- SQL Server 2014 Service Pack 2 SQL Server 2014 Service Pack 2
- SQL Server 2016 Service Pack 1 SQL Server 2016 Service Pack 1
The XML attribute will not appear your query plan if the service pack level is lower than the list above or on a SQL Server version lower than SQL Server 2012.
如果Service Pack级别低于上面的列表或SQL Server版本低于SQL Server 2012,则XML属性将不会出现在您的查询计划中。
Estimated Number of Rows to be Read is another new XML attributed introduced in SQL Server 2016 Service Pack 1. But to diagnose query plan with residual predicate, this article will focus on the XML attribute Number of Rows Read.
预计要读取的行数是SQL Server 2016 Service Pack 1中引入的另一个新XML属性。但是,为了诊断带有残留谓词的查询计划,本文将重点介绍XML属性“已读取行数” 。
XML attribute | Description |
Number of Rows Read (**New) | Number of actual rows accessed by SQL Server. In this example, SQL Server read 2,585 rows |
Actual Number of Rows | Number of rows output from the index seek operation. In the example, all the 2,585 rows satisfies the condition in the index seek |
XML属性 | 描述 |
读取的行数(**新) | SQL Server访问的实际行数。 在此的示例SQL Server读取2,585行 |
实际行数 | 索引查找操作输出的行数。 在该示例中,所有2,585行都满足索引查找中的条件 |
In this scenario where there is no residual predicate, the Index Seek operator properties shows that SQL Server reads and outputs the same number of rows. It means that SQL Server only reads the rows that it requires and spool the rows to the next operator.
在没有剩余谓词的这种情况下,“索引查找”运算符属性显示SQL Server读取并输出相同数量的行。 这意味着SQL Server仅读取其所需的行,并将其后台处理到下一个运算符。
带有谓词的索引搜索 (Index Seek with Residual Predicate)
The first scenario is an Index Seek with Seek Predicates. We will now modify the query slightly and introduce a second predicate on column [Stock Item Key] into the query. Since this column is an included column in the index definition IX_SQLShack_StockItemKey, SQL Server would still be able to perform an index seek on the same non-clustered index.
第一种情况是带有搜索谓词的索引搜索。 现在,我们将稍微修改查询,并在查询中的[Stock Item Key]列上引入第二个谓词。 由于此列是索引定义IX_SQLShack_StockItemKey中的包含列,因此SQL Server仍将能够对同一非聚集索引执行索引查找。
The query plan looks the same as before and the logical reads incurred are still 22 reads. The query returns 13 rows, but the statistics I/O reads is same as if 2,585 rows were read.
查询计划看起来与以前相同,并且发生的逻辑读取仍然是22个读取。 该查询返回13行,但是统计信息I / O读取与读取2585行相同。
Looking at the Index Seek operator properties, SQL Server read 2,585 rows (indicated by the new XML attribute Actual Number of Rows), then performs a filtering based on the Predicate ([Stock Item Key] = 173) and the actual rows spooled to the next operator is only 13 rows (indicated by the Actual Number of Rows).
查看“索引查找”运算符属性,SQL Server读取2,585行(由新的XML属性“ 实际行数”表示 ),然后根据谓词([Stock Item Key] = 173)和后台处理的实际行执行筛选。 next运算符只有13行(由实际行数指示)。
残留谓词下推的说明 (Explanation on Residual Predicate Pushdown)
We can learn a bit more about residual predicate behaviour using an undocumented trace flag 9130. Before SQL Server introduced Number of Rows Read attribute, trace flag 9130 is the workaround to troubleshoot queries which contains residual predicate.
我们可以使用未记录的跟踪标志9130了解有关残余谓词行为的更多信息。在SQL Server引入“读取的行数”属性之前,跟踪标志9130是解决包含残余谓词的查询的变通方法。
We will use the trace flag as a query option as below.
如下所示,我们将使用跟踪标志作为查询选项。
What the trace flag shows us is that SQL Server first reads all the 2,585 rows into memory, then evaluate each row and discard rows which do not satisfy the condition in the Filter operator based on the second predicate. This explains why the same I/O reads were incurred by both queries in the two scenarios.
跟踪标志向我们显示的是SQL Server首先将所有2,585行读取到内存中,然后评估第二行并基于第二个谓词丢弃不满足Filter运算符中条件的行。 这就解释了为什么在两种情况下两个查询都会产生相同的I / O读取。
残留谓词对性能的影响 (Performance Impact due to Residual Predicate)
We now move on to an example to compare the query performance of an Index Seek with and without residual.
现在我们来看一个示例,比较带有和不带有残差的索引搜索的查询性能。
We will use the query below as an example. One of the reasons to use query hint LOOP JOIN is the ease in demonstrating a scenario where residual predicate can really hurt query performance.
我们将使用以下查询作为示例。 使用查询提示LOOP JOIN的原因之一是很容易地说明残余谓词确实会损害查询性能的情况。
The query incurred 127,851 logical reads on [Fact].[Order] table and took almost 3 seconds to complete execution. The Index Seek properties indicate that SQL Server read over 19 million rows into memory, but really only requires 92,781 rows.
该查询对[Fact]。[Order]表进行了127,851次逻辑读取,并花费了近3秒钟来完成执行。 索引查找属性指示SQL Server将超过1900万行读入内存,但实际上仅需要92,781行。
We will now create another index definition and forces the query to use this index instead.
现在,我们将创建另一个索引定义,并强制查询使用该索引。
This query incurred 40,332 logical reads on [Fact].[Order] table and took less than half second to complete execution. This query is 6 times faster without residual. In this scenario, SQL Server pushes the filter down to the table access operator itself and only read exactly 98,781 rows that it needs.
该查询在[Fact]。[Order]表上进行了40,332个逻辑读取,并且不到半秒即可完成执行。 此查询速度快了6倍,没有残留。 在这种情况下,SQL Server将筛选器下推到表访问运算符本身,并且仅准确读取它需要的98,781行。
摘要 (Summary)
Predicate pushdown is important because you would want SQL Server to filter the results as early as possible in the query plan. The more rows that SQL Server operator has to access, the longer the operation will take.
谓词下推很重要,因为您希望SQL Server在查询计划中尽早筛选结果。 SQL Server操作员必须访问的行越多,操作所需的时间就越长。
A Residual predicate scenario can occur in many forms and scenarios other than the examples in this article. Understanding the behaviour of residual predicates will allow better analysis in relation to performance tuning and troubleshooting.
除本文中的示例以外,残留谓词方案可以多种形式出现。 了解残差谓词的行为将允许在性能调整和故障排除方面进行更好的分析。
In addition, SQL Server now has introduced new XML attributes to better diagnose query plans that involve residual predicate pushdown.
此外,SQL Server现在引入了新的XML属性,以更好地诊断涉及残留谓词下推的查询计划。
翻译自: https://www.sqlshack.com/the-impact-of-residual-predicates-in-a-sql-server-index-seek-operation/
sql 键查找 索引查找