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

mis*_*tee 119 performance index sql-server optimization

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

编辑: 上述索引从 DMV 获取信息,这些信息告诉您数据库引擎将用于索引的内容(如果它们可用),并且脚本采用 Top x 推荐(通过搜索、用户影响等)并将它们放在表中。

(上面的编辑部分摘自 Larry Coleman 的回答,以阐明脚本在做什么)

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

我是否需要运行 SQL Profiler,还是检查查询表的代码更好?你还有什么建议吗?

Jer*_*hka 85

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

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

Jason Strate 的新脚本索引分析博客文章(新位置)

最近,我在执行索引分析时使用sp_BlitzIndex®


Mat*_*t M 52

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

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

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

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

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

我知道这是一个有点啰嗦的答案,但确实有很多因素可以确定索引的有效性,并且您必须权衡任何性能提升的因素。


小智 31

我最近从 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/en-us/library/aa933131(v=sql.80).aspx

重组/重建

您应该检查是否存在碎片索引。有点碎片化就好了,不要太执着!http://technet.microsoft.com/en-us/library/ms189858.aspx知道重组和重建的区别!

定期复查

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

多少

在最近的一个视频中,布伦特建议(通常)在一个有大量写入的表(例如订单表)上不要超过 5 个索引,如果读取多于写入(即用于分析的日志记录表),则不要超过 10 个索引http:/ /www.youtube.com/watch?v=gOsflkQkHjg

总体

这取决于!

您的里程因数据库而异。在您的(现在/将来)更大的桌子上覆盖明显的(员工姓氏、订单日期等)。必要时进行监控、审查和调整。在管理您的数据库时,它应该是您日常检查清单的一部分:)

希望这可以帮助!


Rem*_*anu 14

通常情况下,通过具有特定的工作负载(查询)并仔细测试每个新索引对工作负载的影响。此迭代过程应始终包括对执行计划的仔细分析,这将揭示使用了哪些索引。分析查询的主题很长,从专门的 MSDN 章节分析查询开始是一个不错的选择。

有时,当工作负载太复杂或数据库设计的知识很粗略时,可以使用数据库引擎优化顾问,它会对您的工作负载进行一些自动分析并提出一些索引。当然,应仔细分析这些建议,并立即衡量其影响。

因此,如果您遵循我的想法,添加索引并测量影响实际上只是A/B 测试的一个案例:您在没有索引的情况下运行工作负载作为基线,然后使用索引运行它,测量并比较与基线,然后根据观察和测量的指标决定影响是否有益。工作负载最好是质量好的测试套件,但它也可以是捕获的工作负载的重放,请参阅如何:重放跟踪文件

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


小智 8

从 SQL 2005 开始,SQL Server 有DMV告诉您数据库引擎将用于索引的内容(如果它们可用)。视图可以告诉您哪些列应该是关键列,哪些列应该被包含,最重要的是,索引将被使用多少次。

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

另请参阅:官方 MS DMV 文档


jit*_*bit 6

现在是 2021 年了,我决定再添加一个答案。

最新版本的 SQL Server 附带了一个非常方便的新功能,称为查询存储

为数据库启用它后,您可以在一段时间内查看最“昂贵”的查询(CPU 方面或 I/O 方面)、“运行时间最长”的查询等。而且,最重要的是,检查他们的执行计划

查看执行计划通常会给您提供明确的索引建议。但即使没有,您也总是可以知道为什么特定查询很慢(通过在计划中发现“扫描”等)

附言。我个人的偏好是查看“执行时间排名最高的查询”b/c,它不仅会告诉您查询的速度有多慢,还会告诉您执行的频率。因为有时“慢”查询是可以的,如果它每周在周日运行一次。但是每秒运行 100 次的“快速”查询会使服务器变得缓慢。

在此输入图像描述