我经常需要对没有正确索引的大表运行查询。因此,我要求DBA创建此类索引。他要做的第一件事是查看表统计信息,并查看索引空间大小。

他经常告诉我找到一个替代解决方案,因为“索引已经大于表”。他认为索引必须小于数据,因为他告诉我“您见过书中的索引吗?它比书本小得多,这就是表索引应该的样子。”

我不认为他的哲学是正确的,但是我不能挑战他,因为他是首席DBA,而我是一名开发人员。我觉得如果查询需要索引,则应该仅创建索引,而不是查找只会使SP变得不可读和无法维护的“替代方法”。

我仅选择所需的列。问题是我按日期进行筛选,因此引擎必须进行表扫描以匹配列。该查询每天晚上运行一次,以收集统计信息,但是运行需要15分钟(我们有另一条严格的规则:任何过程都不应超过3分钟)。

DBA显示了我的索引统计。该表上大约有10个索引,其中只有6个被使用(统计数据显示零命中4个)。这是一个大型系统,有20多个开发人员参与。索引是出于任何原因而创建的,可能不再使用。

我们需要支持SQL Server 2008,因为这就是测试数据库所运行的。但是客户都在2014年和2016年。

#1 楼

将索引设计想像成滑动开关。您可以将红色三角形开关旋钮沿所需的线移动到任意位置:



我通常不会用尺寸来衡量-我通常会想到它就索引数量而言,但大小也可以。

听起来您的DBA认为切换太右移了-您添加了太多索引,并删除了/更新/插入的执行速度太慢。

与其争论交换机的位置,不如问他有关索引数量过多带来的性能问题。也许您的用户在抱怨删除/更新/插入速度,或者他看到锁等待,或者由于数据库的大小而在备份数据库时遇到了困难。

我的起点通常是5和5 :每个表大约5个索引,每个索引大约5个或更少的字段。这个数字没有什么神奇的-它仅来自于我每只手上有五个手指的事实,因此很容易举起手来解释规则。

您可能需要少一些当工作负载严重偏向于删除/更新/插入操作,并且没有足够的硬件能力来保持索引时,索引将大于5。

当工作负载时,您可以拥有许多索引大部分是只读的,或者您在硬件上进行了大量投资(例如将整个数据库缓存在内存中,并在其下面拥有所有固态存储)。

评论


对于您说的未使用的4个索引,我也感到很好奇。他们为什么还在那里?我认为要做的第一件事就是删除不再需要/不再需要的任何东西。确定这可能很棘手,但这仍然是一个很好的第一步。

–肯尼斯·费舍尔
20 Jan 10 '14 at 14:32

@KennethFisher我认为您回答了错误的内容-您回答了我的答案,而不是问题。

–布伦特·奥扎(Brent Ozar)
20年1月10日在18:12

#2 楼

我喜欢布伦特的答案,并对此表示赞同。我想补充一点。我曾经作为用户,开发人员和DBA工作过,觉得这些意见无关紧要。我认为,由用户(或利益相关者)决定查询的执行方式以及获取结果所需的时间。然后,由开发人员和DBA共同努力以实现这一目标。查询设计或为性能回答。

如果无法修改查询和/或数据结构以实现目标,那么我认为可以归结为三个选择。


数据检索速度慢
数据更新速度慢
更多硬件资源$$$$

当然,每种情况都有很多变量,取决于多种业务和技术因素,但是我相信这三种选择适用于大多数情况并非所有情况。

评论


一个人只能对这个答案投票一次,真是可惜。它价值一百万点……尤其是有关开发人员和DBA共同努力以实现目标的部分。说得好,@ Joe!。

–杰夫·摩登(Jeff Moden)
19/12/30在17:28

#3 楼

此外,在表上拥有超过“ Ozar 5”索引的愿望可能表明您在表上有许多不同种类的读取繁重的查询。

这可能表明您可以从表上的群集或非群集列存储索引中受益。

列存储不再为N个不同的访问路径中的每一个提供最佳索引,而是为您提供了超快速的扫描功能,并能够跳过不需要的列和行段。因此,您可以拥有少量的BTree索引用于超关键事务,而后退到列存储进行其他所有操作。 。请参阅有关实时运营分析的文档。

评论


许多DBA仍然没有听说过列存储索引。

– Endrju
20年1月2日,9:03

#4 楼

似乎过于严格以至于不能禁止索引>表。如果您的表很少更改(或在没有太多资源竞争的夜晚更改),并且以许多不同的方式查询了很多表,则可以证明许多大索引是合理的。 DBA还应注意不要将它不属于自己的鼻子摆在鼻子上。如果他为您/您的系统提供了千兆字节的限制,那么他就不必太在乎该空间的使用情况。如果他劳累过度,这可能就是原因。

但是要考虑很多事情:


很多索引会使插入/更新/删除操作变慢。因此,如果您的
表有很大变化,请注意不要做太多。
空间也是一个问题。不仅因为千兆字节要花费很多钱(如今
还不多),而且备份后的时间也将变慢(取决于
备份的方式)。
可以监视大多数重要的数据库来查找
很少使用或从未使用过的索引。考虑删除其中的一些。
有时您认为您需要索引,但是当您更仔细地检查
查询时,可以对其进行调整和
以不同的方式写入,结果相同,而无需
索引。使用说明计划可以查看是否使用了索引。
有时可以从多列索引中删除最后一列,而不会影响性能。有时这甚至可以使查询更快
,因为索引存储空间较小,并且在任何给定时间将更多索引存储/缓存在内存中。
基于函数的索引可以代替普通索引节省更多空间。示例:
而不是查询完整的姓氏,而是查询前两个字母
where substr(surname, 1, 2) = substr(<userinput>, 1, 2) and surname=<userinput>)和create index i on customers(substr(surname,1,2))。这可能足够快
,并且您的索引会更小。
数据库支持不同类型的索引。某些类型比其他类型使用更少的空间。也许您的某些索引可以转换为较少空间的类型?请务必先了解不同之处
索引类型以及它们的优缺点。
如果不频繁的批处理作业是唯一需要特定索引的事物,请考虑只为该批处理作业创建该索引,然后将其删除。
br />