SQL Server:UNION ALL查询中的同一表上具有多个索引的优化器智能

时间:2018-12-03 18:34:50

标签: tsql optimization indexing database-performance

我正在尝试为一个相当大的表(一个典型的大小为1000万以上)编写查询,该查询的结果需要根据一些业务逻辑在各种谓词/条件上进行过滤。我的问题是:查询优化器(在SQL Server 2008+中)是尝试对整个查询使用单个索引,还是在逐个查询的基础上尝试使用不同的索引?

请考虑以下内容:

--Use Index A
SELECT Set1 
FROM ATable
WHERE AColumn = sarg-able value

UNION ALL

--Are we stuck with Index A?
SELECT Set2 
FROM ATable
WHERE BColumn = sarg-able value

如果我们为Set1选择索引A,是对整个查询都停留在索引A上,还是优化器足够聪明,可以为Set2使用不同索引(假设存在一个索引)?

2 个答案:

答案 0 :(得分:2)

@andreyNikolov所说的一切都是正确的。您可以通过查看实际执行计划(而不是估算的执行计划)轻松地自己弄清楚这种事情。请注意以下示例数据,表和索引结构:

USE tempdb -- safe place in Dev to test this kind of thing...
GO

-- sample data and indexes
IF OBJECT_ID('dbo.ATable','U') IS NOT NULL DROP TABLE dbo.ATable
CREATE TABLE dbo.ATable
(
  Set1    INT NOT NULL,
  Set2    INT NOT NULL,
  AColumn INT NOT NULL,
  BColumn INT NOT NULL
);

INSERT dbo.ATable (Set1, Set2, AColumn, BColumn)
VALUES (1,2,3,3),(1,2,4,4),(5,5,6,6),(11,22,40,40),(11,20,40,44),(11,22,14,4),(1,2,3,3);

CREATE NONCLUSTERED INDEX indexA ON dbo.ATable(AColumn) INCLUDE(Set1);
CREATE NONCLUSTERED INDEX indexB ON dbo.ATable(BColumn) INCLUDE(Set2);

现在,在打开“包括实际执行计划”的情况下运行以下命令。

SELECT Set1 --Use Index A
FROM   dbo.ATable
WHERE  AColumn = 3
UNION ALL
SELECT Set2 --Use Index B
FROM   dbo.ATable
WHERE BColumn = 4;

...和执行计划:

enter image description here

UNION ALL上方的查询对IndexA的键列(AColumn)执行非聚集的 seek 。因为我将Set1作为IndexA的include列包含在内,所以IndexA可以满足查询而无需进行Rid或Key查找。这就是索引的设计方式。除了使用IndexB之外,UNION ALL下的查询也是如此。

同样,一旦您完全了解如何阅读执行计划,这种事情就很容易由您自己弄清楚。

答案 1 :(得分:1)

是的,优化器足够聪明。这是两个单独的操作,可以作为表/索引扫描或查找来执行。执行每个索引的决定是独立的,并且对每个索引使用不同的索引是完全正常的。然后将两个操作的结果合并。