如果不使用所有列,我的索引会被使用吗?

问题描述 投票:15回答:8

我在表T的A,B,C,D列上有一个索引

我有一个查询,它在WHERE子句中使用A,B,C从T中提取。

是否会使用索引或是否需要一个仅包含A,B,C的单独索引?

sql sql-server sql-execution-plan
8个回答
10
投票

David B是正确的,您应该检查执行计划以验证索引是否正在使用。

Will the index be used or will a separate index be needed that only includes A, B, C?

要回答问题的最后一部分,我认为这是核心的基础主题(而不是直接的解决方案),几乎没有理由索引索引列的子集。如果您的索引是(A,B,C,D),WHERE对(A,B,C)最有可能导致索引搜索,这是理想的情况 - 索引包含引擎需要的所有信息直接进入结果集。我相信这对数字类型和字符串类型中的相等测试都适用,尽管它可以与LIKE'%'分解。另一方面,如果你的WHERE只引用了D,你最有可能最终会进行索引扫描,这意味着SQL引擎必须扫描A,B和C的所有组合,然后检查是否D在决定是否将行添加到结果集之前满足您的条件。在一个特别大的表上,当我发现自己不得不对列“D”进行大量查询时,我只为D添加了一个额外的索引,并且看到了大约90%的性能提升。

编辑:我还应该建议在SQL Management Studio中使用数据库引擎优化顾问。它将告诉您表是否未针对要运行的查询进行理想的索引编制。


8
投票

这取决于!

WHERE A like '%x%'
  and B = 1
  and C = 1
//
WHERE A = 1
  OR B = 1
  OR C = 1
//
WHERE DateAdd(dd, 1, A) = '2008-01-01'
  AND B = 1
  AND C = 1

这些不依赖于索引,因为索引没用。

单击“显示估计执行计划”以确认潜在的索引使用情况。


5
投票

在Oracle数据库中,这被称为Composite Index(12g文档但对早期版本有效)

复合索引可以加速检索SELECT语句的数据,其中WHERE子句引用复合索引中列的所有前导部分。因此,定义中使用的列的顺序很重要。通常,最常访问的列首先出现。

在你的情况下,是的。该指数将/可以使用。这可以通过使用解释计划来验证。

如果MS SQLSERVER不同(我怀疑它可能),你需要一个新的答案。

编辑:还应该提到它只会考虑使用索引..这并不一定意味着它会使用它。

Edit2:Oracle 11g及更高版本现在有一个选项,允许它跳过索引中的列。所以对A,B和D的查询可能仍然使用索引


4
投票

索引将被使用,是的。关于哪些索引会产生更优化的查询计划是相当明智的,它应该没有问题。

就像这种事情一样,不要相信我的话 - 对它进行基准测试。创建一个表,用代表性数据填充,查询,索引并再次查询。


2
投票

索引包含未在查询中使用的列的事实不会阻止它被使用。

这并不是说它肯定会被使用,它可能会因为一个不同的原因而被忽略(也许是因为一个或多个其他索引更有用)。

与往常一样,对估计的执行计划进行分解,看看可能发生的事情。


2
投票

从简单的等于查找开始(WHERE A = 1,B ='Red'和C = 287)是的,索引(最有可能)将被使用。首先使用索引来帮助优化器“猜测”与选择匹配的行数,然后再实际访问这些行。

为了回应David B关于“喜欢”谓词的评论,SQLServer仍然可以使用索引,这取决于你选择的内容。例如,如果您选择计数(*),则SQLServer可能会扫描索引并计算与where子句匹配的命中数,因为索引较小并且需要较少的IO才能扫描。即使您从基表中选择一些列,也可能决定这样做,具体取决于SQLServer对索引的选择程度。


1
投票

这是另一个“它取决于”的答案......它还取决于你的桌子有多大......

我同意其他提到检查执行计划以验证您的索引是否被使用的人。

以下是一些关于阅读执行计划的文章,您应该会发现它很有用:

http://www.sqlservercentral.com/articles/Administering/executionplans/1345/ http://www.codeproject.com/KB/database/sql-tuning-tutorial-1.aspx

还有一篇关于搜索和扫描的文章,我建议:http://blogs.msdn.com/craigfr/archive/2006/06/26/647852.aspx

Craig Freedman的博客上有一篇很好的文章记录,这是另一个你应该发现有用的文章。本文是关于SQL Server用于确定使用哪个索引的一些因素...

http://blogs.msdn.com/craigfr/archive/2006/07/13/664902.aspx

照顾自己!杰夫


1
投票

一般来说是的,所有现代数据库都足够聪明地做到这一点。例如,有一些例外情况,如果表中的统计数据显示其中的数据量足够小,使得完整的表读取将更有效,那么索引将被打折,但通常,您可以依赖它在适当情况下。

因此,您可以在设计索引时利用此功能。比方说,我有一个表,其中包含A,B,C作为键值,列Y和Z包含我知道将经常通过语句检索的数据

SELECT Y FROM table WHERE A = alpha and B = beta and C = gamma 

SELECT Z FROM table WHERE A = alpha and B = beta and C = gamma 

我通常会在A,B,C,X,Z上创建一个索引 - 假设X和Z是一个相当小的字段。这样做的原因是我知道上面语句中的访问路径将使用索引,并且由于我想要检索的数据已经在索引读取中,因此不需要单独读取检索表数据本身所需的数据块将需要。在某些情况下,此策略可以显着加快数据检索速度。当然,您需要在更新成本和磁盘空间中支付费用,因此您需要在应用数据库之前了解数据库正在执行的操作,但是在大多数数据库中读取的数据显着超出了写入数量,因此通常值得考虑。

© www.soinside.com 2019 - 2024. All rights reserved.