建议索引

建议索引

我对索引还很陌生,刚刚开始学习查询计划等。我正在研究这个特定的查询,它一直建议我创建以下索引:

CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[Company] ([CreatedById],[TenantId],[CreatedDate])

在此处输入图片描述

我已经创建了以下索引:

CREATE NONCLUSTERED INDEX [IX_Company_Tenant] 
ON [dbo].[Company] ([TenantId],[UserId],[CreatedDate])

我想知道的是,如果我将已经创建的索引更改为:,是否会获得相同的速度提升结果:

CREATE NONCLUSTERED INDEX [IX_Company_Tenant] 
ON [dbo].[Company] ([TenantId],[UserId],[CreatedDate], [CreatedByID])

而不是创建查询存储建议的索引?

编辑

即使应用了第三个索引:

CREATE NONCLUSTERED INDEX [IX_Company_Tenant] 
ON [dbo].[Company] ([TenantId],[UserId],[CreatedDate], [CreatedByID])

我仍然得到相同的建议索引。

答案1

首先,确保在创建索引之间转储该查询的缓存计划。最核心的选项是执行缓存刷新(数据库缓存FREEPROCCACHE) 但您也可以查找计划句柄并只执行特定的一个。我还建议在试验期间删除非聚集索引 - 如果您在这个表上有三个索引,并且都试图加速同一个查询,那么这不是最好的情况。

在考虑创建索引时,请记住 SQL 为您提供的索引创建建议价值有限。SQL 通常正确地表示“我可以使用索引做得更好”,但它实际上没有很好的方法来告诉您最适合您需求的确切索引。

大多数情况下,它会给出次优的列顺序。很多时候它会错过有用的列,或者告诉你放入了太多的列。

一般来说,您需要对导致需要索引的查询有充分的了解,然后创建适合该查询的索引。大多数查询都采用针对某些特定记录集的形式,因此索引中的列按最能找到所需数据的顺序排列。换句话说,如果一列可以消除所有可能结果的 95%,而另一列可以消除 20% 的结果,则将 95% 的列放在首位。

举一个简单的例子,如果我有一个查询,按日期选择一小部分(1%)记录,并通过 50% 的记录所具有的标志消除一些剩余的记录,那么我最好先按日期对索引列进行排序,然后再按标志进行排序。反过来做会让我为相同的最终结果执行更多的工作。

在不了解您的数据的情况下查看您的查询,我猜测它的一个相当不错的索引将是:

CREATE NONCLUSTERED INDEX [IX_Company_Tenant] 
ON [dbo].[Company] ([CreatedDate],[CreatedByID],[TenantId])

这是一篇很好的博客文章,对此进行了更深入的解释 -https://www.brentozar.com/archive/2019/10/how-to-think-like-the-sql-server-engine-adding-a-nonclustered-index/

答案2

您必须按照建议的确切列顺序(或技术上几乎等同的列顺序)创建索引。
列顺序有时/通常对特定查询的索引的可用性和效率很重要。

在上述情况下,重要的是在这些字段CreatedDate后面CreatedByIDTenantId甚至直接后面(因此没有UserId中间)有,以允许 SQL Server 直接跳转到索引块CreatedByIDTenantId然后CreatedDate在该列的连续顺序条目中找到请求的起始值并读取所有行引用,一个接一个地滚动索引,直到达到请求的CreatedDate结束值(并为找到的每一行增加计数器)。

与此相反,请考虑调整后的索引。
SQL Server 可以找到请求的区域TenantId。 但是它必须读取该区域的所有条目TenantId并检查是否CreateDate在范围内,如果在范围内,则必须检查是否CreatedByID满足查询条件。 可能需要进行这些检查的行数可能很多,具体取决于表大小和数据分布。

相关内容