首页 > 解决方案 > SQL Server:优化器智能,在 UNION ALL 查询中的同一个表上有多个索引

问题描述

我正在尝试为一个相当大的表编写查询(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使用不同的索引(假设存在一个索引)?

标签: tsqloptimizationindexingdatabase-performance

解决方案


@andreyNikolov 所说的一切都是 100% 正确的。这是您可以通过查看实际执行计划(未估计执行计划)轻松自行解决的问题。请注意以下示例数据、表和索引结构:

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;

...以及执行计划:

在此处输入图像描述

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

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


推荐阅读