如何确定索引是必需的还是必需的


110

我一直在我们的MS SQL数据库上运行自动索引工具(我修改了源自Microsoft的脚本,该脚本查看索引统计表- 自动化自动索引)。现在,从统计信息中,我可以获得需要创建的索引的建议列表。

编辑: 上述索引从DMV那里获取信息,这些信息告诉您数据库引擎将使用哪些索引(如果索引可用),并且脚本采用Top x建议(按查找,用户影响等)并将它们放在表格中。

(上面的编辑部分摘自拉里·科尔曼(Larry Coleman)在下面的回答,以阐明脚本的作用。

由于我是数据库管理员的新手,并且已经在网上进行了快速搜索,因此我不愿意尝试并盲目添加推荐的索引。但是,由于没有该领域的经验,我正在寻找有关如何确定建议是否必要的建议。

我需要运行SQL事件探查器,还是最好检查查询表的代码?您还有其他建议吗?



检查不可用的索引。这篇文章可以帮助你:sqlshack.com/...
Shiwangini Shishulkar

Answers:


80

我使用Jason Strate的索引分析脚本(旧位置)。它们告诉您使用了多少现有索引以及将使用多少缺失索引。我通常不添加索引,除非它们占表查询的5%或10%以上。

不过,最重要的是,它是要确保应用程序对用户的响应速度足够快。

更新: Jason Strate的索引分析博客文章,用于更新的脚本(新位置)

双重更新:这些天来,我在执行索引分析时使用sp_BlitzIndex®


我们需要对所有表进行哪些更改?
MonsterMMORPG '16

1
sp_BlitzIndex将查看所有超过一定大小的表。您必须去看文档以了解如何调整它。
耶利米·佩斯卡

执行sp_BlitzIndex的参数在此处:brentozar.com/blitzindex
JackArbiter

任何三重更新?
Simon_Weaver

49

在处理索引时,需要理解一些重要的概念和术语。搜索,扫描和查找是通过select语句使用索引的一些方式。键列的选择性对于确定索引的有效性必不可少。

当SQL Server查询优化器确定查找所需数据的最佳方法是通过扫描索引中的范围时,就会进行查找。当查询被索引“覆盖”时,通常会发生搜索,这意味着搜索谓词在索引键中,而显示的列在键中或包含在内。当SQL Server查询优化器确定查找数据的最佳方法是扫描整个索引,然后过滤结果时,即发生扫描。当索引未在索引键或包含的列中不包括所有请求的列时,通常会发生查找。然后,查询优化器将使用聚簇键(针对聚簇索引)或RID(针对堆)“查找”其他请求的列。

通常,由于物理查询较小的数据集,查找操作比扫描更有效。在某些情况下不是这样,例如很小的初始数据集,但是超出了您的问题范围。

现在,您询问了如何确定索引的有效性,并且需要牢记一些注意事项。聚集索引的键列称为聚集键。这就是在聚集索引的上下文中使记录唯一的方式。默认情况下,所有非聚集索引都将包含聚集键,以便在必要时执行查找。对于每个相应的DML语句,所有索引都将插入,更新或删除。话虽这么说,最好是在select语句中的性能提升与插入,删除和更新语句中的性能影响之间取得平衡。

为了确定索引的有效性,必须确定索引键的选择性。选择性可以定义为不同记录占总记录的百分比。如果我有一个[person]表,该记录包含100条记录,并且[first_name]列包含90个不同的值,则可以说[first_name]列具有90%的选择性。选择性越高,索引键越有效。牢记选择性,最好将最具有选择性的列放在索引键的第一位。使用我以前的[person]示例,如果我们的[last_name]列具有95%的选择性,该怎么办?我们想要创建一个以[last_name],[first_name]作为索引键的索引。

我知道这是一个漫长的回答,但是确实有很多事情要决定索引的有效性,并且必须权衡任何性能提升。


1
我只想强调上面所说的内容:索引会使您的插入/删除和更新速度变慢。如果必须说要批量插入大量数据,那么最好不用索引(可以在以后创建索引,这样更快)。
Nicolas de Fontenay

提到[last_name],[first_name]列上的索引仅在查询将根据last_name和first_name进行筛选时才可以使用吗?如果仅对first_name进行过滤,则无法使用索引,可以吗?
马吉尔

好的答案-在决定是否建立索引时,选择性比基数更重要
逆向工程师

27

我最近在BrentOzar Unltd http://www.brentozar.com/blitzindex/上发现了一个很棒的免费脚本

这样可以很好地分析存在哪些索引,使用索引的频率以及查询引擎查找不存在的索引的频率。

它的指导一般都很好。有时,它有点过分地暗示想法。到目前为止,我通常已完成以下操作:

  • 删除从未读过的索引(或每月少于50次)。
  • 在外键和字段上添加了最明显的索引,我知道我们经常使用。

我还没有添加所有推荐的索引,一周后又回过头来发现不再推荐它们了,因为查询引擎正在使用其他一些新索引!

通常,您应该避免以下内容的索引:

  • 很小的表(少于50到200条记录):查询引擎通常会扫描表而不是加载索引,读取,处理等等,因此速度更快。
  • 避免在第一个提到的列上具有低基数(http://en.wikipedia.org/wiki/Cardinality_(SQL_statements))的列上建立索引。例如,索引性别字段(M / F)几乎没有用,扫描表格并找到匹配的〜50%的内容也是一样的实用。如果将其列在索引中更具体的内容之后(例如[出生日期,性别]),则更好-您可能希望所有男性在给定的时间范围内出生。

聚集索引很好-通常,这些索引基于您的主键。它们帮助数据库引擎将数据良好地放置在磁盘上。对于最大的表来说,理解这一点非常重要,因为良好的聚集索引通常会减少表占用的空间。

我将某些表从900MB减少到了400MB,只是因为它们事先是非结构化的堆。 http://msdn.microsoft.com/zh-CN/library/aa933131(v=sql.80).aspx

重组/重建

您应该在检查碎片索引。有点碎片是可以的,不要沉迷!http://technet.microsoft.com/zh-cn/library/ms189858.aspx了解重组和重建之间的区别!

定期审查

查询更改,数据量更改,添加了新功能,删除了旧功能。您应该每月检查一次(如果流量很大,则应更频繁地查看),并寻找可以在哪里帮助数据库!

多少

在最近的一段视频中,Brent建议(通常)在一个具有大量书写的表(例如,订单表)上不要再包含5个索引,并且如果其读取量要大于书面的(即用于分析的日志记录表),则不超过10个索引http:/ /www.youtube.com/watch?v=gOsflkQkHjg

总体

这取决于!

您的里程因数据库而异。在您的(现在/将来)较大的表格上盖上明显的(员工姓,订购日期等)。监视,检查和根据需要进行调整。在管理数据库时,它应该成为例行检查表的一部分:)

希望这可以帮助!


14

通常情况下,需要特定的工作负载(查询)并仔细测试每个新索引对工作负载的影响。该迭代过程应始终包括对执行计划的仔细分析,以揭示所使用的索引。分析查询是一个冗长的话题,从MSDN专门的章节“ 分析查询”开始是一个不错的选择。

有时,当工作负载过于复杂或对数据库设计的了解很粗略时,可以使用Database Engine Tuning Advisor来自动分析您的工作负载并提出一些索引。当然,应仔细分析建议,并应立即评估影响。

因此,如果按照我的想法,添加索引并评估影响实际上只是A / B测试的一种情况:不使用索引作为基线来运行工作负载,然后使用索引来运行它,进行测量和比较然后根据观察和测量的指标确定影响是否有益。工作负载最好是高质量的测试套件,但也可以是捕获的工作负载的重播,请参阅如何:重播跟踪文件

一个更综合的答案是sys.dm_db_index_usage_stats查看视图并查看索引的使用方式,但这通常是一种在未知工作负载上进行现场分析的方法(例如,被称为“帮助”的顾问可能会以此为起点)。


7

从SQL 2005开始,SQL Server具有DMV,可以告诉您数据库引擎将在索引可用时使用什么。这些视图可以告诉您哪些列应该是键列,应该包括哪些列,最重要的是,可以使用索引多少次。

一个好的方法是按搜索次数对丢失的索引查询进行排序,并考虑先添加顶部索引。

另请参阅:官方MS DMV文档


-1

这取决于该表的使用方式。例如,假设我有一个被读取很多次的表,但是很少进行更新和插入。另外,我总是在某些外键列上查询表。在该外键上创建(非聚簇)索引可以加快读取查询的速度。但缺点是,您的插入,更新将变得缓慢。

很少有统计查询可以告诉您查询花费了多少时间。从最慢的开始。如果查询谓词没有索引,则创建索引将有所帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.