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

Tsql SQL Server:优化器智能,在UNION ALL查询中在同一个表上具有多个索引,tsql,optimization,indexing,database-performance,Tsql,Optimization,Indexing,Database Performance,我正在尝试为一个相当大的表编写一个查询(1000万以上是一个典型的大小),其结果需要根据一些业务逻辑根据各种谓词/条件进行过滤。我的问题:查询优化程序(在SQLServer2008+中)是尝试对整个查询使用单个索引,还是尝试对每个查询使用不同的索引 考虑以下几点: --Use Index A SELECT Set1 FROM ATable WHERE AColumn = sarg-able value UNION ALL --Are we stuck with Index A? SELEC

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

考虑以下几点:

--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使用不同的索引(假设存在)?

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

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

安德烈尼科洛夫所说的一切都是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)执行非聚集搜索。因为我在IndexA中将Set1作为include列包含,IndexA可以满足查询,而无需对其进行Rid或键查找。这就是应该如何设计索引。UNION ALL下面的查询也是如此,只是它使用的是IndexB


同样,一旦你对如何阅读执行计划有了充分的了解,这是一种很容易自己弄明白的事情

安德烈尼科洛夫所说的一切都是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)执行非聚集搜索。因为我在IndexA中将Set1作为include列包含,IndexA可以满足查询,而无需对其进行Rid或键查找。这就是应该如何设计索引。UNION ALL下面的查询也是如此,只是它使用的是IndexB


同样,一旦你对如何阅读执行计划有了充分的了解,这是一种很容易自己弄明白的事情

查询优化器将在其小小的虚拟头脑中使用任何应该提高性能的索引。这意味着它可以选择在
a列
上使用索引,而不是简单的索引。更新索引统计信息也可能会改变执行计划(当查询重新编译时),例如,如果索引变得或多或少具有选择性。(对于1000000行,一个具有50000个不同值的索引比一个具有10个不同值的索引更具选择性。或者1。)查询优化器将在其小小的虚拟思维中使用任何应该提高性能的索引。这意味着它可以选择在
a列
上使用索引,而不是简单的索引。更新索引统计信息也可能会改变执行计划(当查询重新编译时),例如,如果索引变得或多或少具有选择性。(对于1000000行,具有50000个不同值的索引比具有10个不同值的索引更具选择性。或1。)