索引空间大于数据空间是否不好?


22

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

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

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

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

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

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

Answers:


34

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

索引设计决策

我通常不以大小来衡量它-我通常以索引数量来衡量它,但是大小也可以。

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

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

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

当您的工作负载严重偏向于删除/更新/插入操作,并且您没有足够的硬件功能来维持时,您可能需要具有少于5个的LESS索引。

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


4

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

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

列存储不再为N个不同的访问路径中的每一个提供最佳索引,而是为您提供了超快速的扫描功能,并能够跳过不需要的列和行段。因此,您可以拥有少量的BTree索引用于超关键事务,而对于其他所有事务,则退回到列存储。

列存储索引旨在与SQL Server 2016+一起处理OLTP繁重的工作负载。请参阅有关实时运营分析的文档。


3

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

如果您公司的DBA职位“负责”他们可以分析您的查询,并为更好的查询设计提出建议,或者对性能进行回答。

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

  1. 缓慢的数据检索
  2. 数据更新缓慢
  3. 更多硬件资源$$$$

当然,每种情况都有多种变数,取决于多种业务和技术因素,但我认为这三种选择适用于大多数(即使不是全部)情况。


0

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

但是,有很多事情要考虑:

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