Seek Predicate 和 Predicate 的区别

Gre*_*reg 15 performance execution-plan sql-server-2014 query-performance

我正在尝试对 SQL Server 2014 Enterprise 中的查询进行性能优化。

我已经在 SQL Sentry Plan Explorer 中打开了实际的查询计划,我可以在一个节点上看到它有一个Seek Predicate和一个Predicate

什么之间的区别寻求谓词谓词

在此处输入图片说明

注意:我可以看到这个节点有很多问题(例如估计行与实际行、剩余 IO),但问题与任何这些都无关。

Joe*_*ish 22

让我们将一百万行连同几列一起放入临时表中:

CREATE TABLE #174860 (
PK INT NOT NULL, 
COL1 INT NOT NULL,
COL2 INT NOT NULL,
PRIMARY KEY (PK)
);

INSERT INTO #174860 WITH (TABLOCK)
SELECT RN
, RN % 1000
, RN % 10000
FROM 
(
    SELECT TOP 1000000 ROW_NUMBER () OVER (ORDER BY (SELECT NULL)) RN
    FROM   master..spt_values v1,
           master..spt_values v2
) t;

CREATE INDEX IX_174860_IX ON #174860 (COL1) INCLUDE (COL2);
Run Code Online (Sandbox Code Playgroud)

在这里,我在PK列上有一个聚集索引(默认情况下)。有一个非聚集索引COL1,它的键列是COL1并且包括COL2

考虑以下查询:

SELECT *
FROM #174860
WHERE PK >= 15000 AND PK < 15005
AND COL2 = 5000;
Run Code Online (Sandbox Code Playgroud)

在这里我没有使用,BETWEEN因为 Aaron Bertrand 一直在讨论这个问题。

SQL Server 优化器应该如何查询?嗯,我知道过滤器PK会将结果集减少到五行。SQL Server 可以使用聚集索引跳转到这五行,而不是读取表中的所有百万行。但是,聚集索引只有 PK 列作为键列。一旦该行被读入内存,我们需要在 上应用过滤器COL2。这里,PK是一个搜索谓词,COL2是一个谓词。

在此处输入图片说明

SQL Server 使用搜索谓词找到五行,并使用正常谓词将这五行进一步减少为一行。

如果我以不同的方式定义聚集索引:

CREATE TABLE #174860 (
PK INT NOT NULL, 
COL1 INT NOT NULL,
COL2 INT NOT NULL,
PRIMARY KEY (COL2, PK)
);
Run Code Online (Sandbox Code Playgroud)

并运行相同的查询我得到不同的结果:

在此处输入图片说明

在这种情况下,SQL Server 可以使用WHERE子句中的两列进行查找。使用键列从表中读取正好一行。

再举一个例子,考虑这个查询:

SELECT *
FROM #174860
WHERE COL1 = 500
AND COL2 = 3545;
Run Code Online (Sandbox Code Playgroud)

IX_174860_IX 索引是一个覆盖索引,因为它包含查询所需的所有列。然而,只是COL1一个键列。SQL Server 可以使用该列查找具有匹配COL1值的 1000 行。它可以进一步过滤列上的那些行,COL2以将最终结果集减少到 0 行。

在此处输入图片说明