如果不使用所有列,是否将使用我的索引?

时间:2020-03-06 14:44:39  来源:igfitidea点击:

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

我有一个查询,该查询从WHERE子句中的A,B,C的T中提取。

是使用索引还是仅包含A,B,C的单独索引?

解决方案

在Oracle数据库中,这称为综合索引(12g文档,但对早期版本有效)

Composite indexes can speed retrieval of data for SELECT statements in which the WHERE clause references all of the leading portion of the columns in the composite index. Therefore, the order of the columns used in the definition is important. In general, the most commonly accessed columns go first.

所以就我们而言,是的。该索引将/将被使用。这可以通过使用解释计划进行验证。

如果MS SQLSERVER不同(我怀疑可能是这样),则需要一个新的答案。

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

编辑2:
Oracle 11g及更高版本现在具有一个允许其跳过索引中的列的选项。因此对A,B和D的查询可能仍会使用索引

这取决于!

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

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

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

将使用索引,是的。关于哪个索引将产生更优化的查询计划是相当明智的,并且这样做应该没有问题。

对于这种事情,请不要相信我所说的。创建一个表,用代表性数据填充表,对其进行查询,索引并再次查询。

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

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

像往常一样,对估计的执行计划进行打量,以查看可能发生的情况。

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

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

一般来说,是的,所有现代数据库都足够聪明地做到这一点。有例外,例如,如果表上的统计信息表明表中的数据量足够小,以至于全表读取将更有效,则索引将被打折,但通常,我们可以在适当的情况下依赖它。

因此,在设计索引时可以利用此优势。例如,我有一个表,其中包含作为键值的A,B,C和列Y和Z,其中包含我知道的数据,这些数据经常由语句检索

从表中选择Y,其中A =字母B,B = beta,C =伽马

从表中选择Z,其中A =字母B = beta字母C =伽玛

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

David B是正确的,我们应该检查执行计划以确认正在使用索引。

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

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

编辑:我还建议我们在SQL Management Studio中使用数据库引擎优化顾问。它会告诉我们表是否不是要运行的查询的理想索引。

这是另一个"视情况而定"的答案...这还取决于桌子有多大...

我同意提到检查执行计划以验证索引是否正在使用的其他所有人的观点。

这里有几篇关于阅读执行计划的文章,我们会发现它们很有用:

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

小心!
杰夫