我一直在我们的 MS SQL 数据库上运行一个自动索引工具(我修改了一个源自 Microsoft 的脚本,它查看索引统计表 -自动自动索引)。从统计数据中,我现在有一个需要创建的索引的建议列表。
编辑: 上述索引从 DMV 获取信息,这些信息告诉您数据库引擎将在索引可用时将其用于索引,并且脚本采用 Top x 建议(通过搜索、用户影响等)并将它们放在一个表中。
(上面的编辑部分取自拉里科尔曼的回答,以澄清脚本在做什么)
由于我是数据库管理员的新手,并且在网上进行了快速搜索,因此我不愿意冒险并盲目地添加推荐的索引。但是,由于没有该领域的经验,我正在寻找一些关于如何确定这些建议是否必要的建议。
我是否需要运行 SQL Profiler,还是最好检查查询表的代码?你还有什么其他建议吗?
我使用Jason Strate 的索引分析脚本。它们告诉您使用了多少现有索引以及将使用多少缺失索引。我通常不添加索引,除非它们占表上查询的 5% 或 10% 以上。
不过,最重要的是,它是为了确保应用程序对用户的响应速度足够快。
Jason Strate 的指数分析博客文章)
这些天来,我在执行索引分析时使用sp_BlitzIndex® 。
在处理索引时,有一些重要的概念和术语需要理解。查找、扫描和查找是通过 select 语句使用索引的一些方式。关键列的选择性对于确定索引的有效性是不可或缺的。
当 SQL Server 查询优化器确定查找您请求的数据的最佳方法是扫描索引内的范围时,就会发生查找。搜索通常发生在查询被索引“覆盖”时,这意味着搜索谓词在索引键中,并且显示的列在键中或包含在内。当 SQL Server 查询优化器确定查找数据的最佳方法是扫描整个索引然后过滤结果时,就会发生扫描。当索引不包括所有请求的列时,通常会发生查找,无论是在索引键中还是在包含的列中。然后,查询优化器将使用聚集键(针对聚集索引)或 RID(针对堆)“查找”其他请求的列。
通常,由于物理查询较小的数据集,查找操作比扫描更有效。在某些情况下情况并非如此,例如非常小的初始数据集,但这超出了您的问题范围。
现在,您询问了如何确定索引的有效性,并且需要记住一些事项。聚集索引的键列称为聚集键。这就是在聚集索引的上下文中使记录唯一的方式。默认情况下,所有非聚集索引都将包含聚集键,以便在必要时执行查找。将为每个相应的 DML 语句插入、更新或删除所有索引。话虽如此,最好在 select 语句中的性能提升与 insert、delete 和 update 语句中的性能命中之间取得平衡。
为了确定索引的有效性,您必须确定索引键的选择性。选择性可以定义为不同记录占总记录的百分比。如果我有一个包含 100 条记录的 [person] 表,并且 [first_name] 列包含 90 个不同的值,我们可以说 [first_name] 列具有 90% 的选择性。选择性越高,索引键的效率越高。牢记选择性,最好将最具选择性的列放在索引键的首位。使用我之前的 [person] 示例,如果我们有一个 95% 选择性的 [last_name] 列怎么办?我们希望创建一个以 [last_name], [first_name] 作为索引键的索引。
我知道这是一个有点啰嗦的答案,但确实有很多事情可以确定索引的有效性,而且很多事情你必须权衡任何性能提升。
我最近从 BrentOzar Unltd http://www.brentozar.com/blitzindex/的人们那里发现了一个很棒的免费脚本
这可以很好地分析哪些索引存在,它们的使用频率以及查询引擎查找不存在的索引的频率。
它的指导通常很好。有时它会有点过度暗示想法。到目前为止,我通常做了以下工作:
我还没有添加所有推荐的索引,并且一周后返回发现不再推荐它们,因为查询引擎正在使用其他一些新索引!
一般来说,你应该避免索引:
聚集索引很好——通常这些索引基于您的主键。它们帮助数据库引擎将磁盘上的数据井井有条。对于最大的表来说理解这一点非常重要,因为一个好的聚集索引通常会减少表占用的空间。
我已经将一些表从 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
全面的
这取决于!
您的里程因数据库而异。在您的(现在/未来)较大的桌子上覆盖明显的(员工姓氏、订单日期等)。必要时进行监控、审查和调整。在管理数据库时,它应该是您日常检查清单的一部分:)
希望这可以帮助!
通常,通过具有特定的工作负载(查询)并仔细测试每个新索引对工作负载的影响。这个迭代过程应该始终包括对执行计划的仔细分析,这将揭示使用了哪些索引。分析查询的主题很长,从专门的 MSDN 章节Analyzing a Query开始是一个不错的选择。
有时,当工作负载太复杂或数据库设计知识很粗略时,可以使用数据库引擎优化顾问,它会对您的工作负载进行一些自动分析并提出一些索引。当然,应仔细分析这些建议,并立即衡量其影响。
因此,如果您遵循我的想法,添加索引并衡量影响实际上只是A/B 测试的一个案例:您在不使用索引作为基线的情况下运行工作负载,然后使用索引运行它,测量和比较与基线,然后根据观察和测量的指标决定影响是否有益。工作负载最好是一个高质量的测试套件,但它也可以是捕获的工作负载的重放,请参阅如何:重放跟踪文件。
一个更综合的答案是
sys.dm_db_index_usage_stats
查看视图并了解如何使用索引,但这通常是对未知工作负载进行现场分析的一种方法(即,一个被要求提供帮助的顾问可能会从这个开始)。从 SQL 2005 开始,SQL Server 具有DMV,可以告诉您数据库引擎将使用哪些索引(如果可用)。视图可以告诉你哪些列应该是关键列,哪些列应该被包含,最重要的是,索引会被使用多少次。
一个好的方法是按查找次数对丢失的索引查询进行排序,并考虑首先添加顶部索引。
另见:官方 MS DMV 文档
现在是 2021 年,我决定再添加一个答案。
最新版本的 SQL Server 带有一个非常方便的新功能,称为查询存储
在为数据库启用它之后,您可以在一段时间内查看最“昂贵”的查询(CPU 方面或 I/O 方面)、“运行时间最长”的查询等。而且,最重要的是,检查他们的执行计划。
查看执行计划通常会给您明确的索引建议。但即使没有,您也可以随时判断特定查询为何缓慢(通过在计划中发现“扫描”等)
PS。我个人的偏好是查看“按总执行时间排列的热门查询”b/c,它不仅会告诉您查询有多慢,还会告诉您执行的频率。因为有时“慢”查询很好,如果它在星期日每周运行一次。但是每秒运行 100 次的“快速”查询会导致服务器运行缓慢。
这取决于该表的使用方式。例如,假设我有一张被多次读取但更新和插入很少的表。另外,我总是在某些外键列上查询表。在该外键上创建(非聚集)索引以加快读取查询是有意义的。但缺点是,您的插入、更新会变慢。
很少有统计查询可以说明查询花费了多少时间。从最慢的开始。如果查询谓词没有索引,创建一个会有所帮助。