什么时候创建统计信息而不是创建索引更好?


38

我发现了很多有关什么 的信息STATISTICS:如何维护它们,如何从查询或索引手动或自动创建它们,等等。但是,我无法找到有关何时使用的任何指导或“最佳做法”信息创建它们:在什么情况下,手动创建的STATISTICS对象比从Index中受益更多。我已经看到了手动创建的筛选统计信息,可以帮助对分区表进行查询(因为为索引创建的统计信息涵盖整个表,而不是每个分区-太小了!),但是肯定还有其他情况可以从统计对象中受益不需要索引的详细信息,也不需要花费维护索引或增加阻塞/死锁机会的成本。

@JonathanFite在评论中提到索引和统计数据之间的区别:

索引将通过创建与表本身排序不同的查找来帮助SQL更快地找到数据。统计信息可帮助SQL确定满足查询所需的内存/工作量。

那是个很棒的信息,主要是因为它可以帮助我阐明我的问题:

如何知道这(或在任何其他技术信息什么 S和如何 S的相关的行为和性质STATISTICS)帮助确定何时选择CREATE STATISTICSCREATE INDEX创建索引将创建相关的时候,尤其是STATISTICS对象?具有统计信息而不具有索引会更好地服务于哪种情况?

如有可能,提供一个工作场景示例,说明该STATISTICS对象比物体更合适,这对超级骗子很有帮助INDEX


因为我是一个视觉学习者/思想家,所以我认为并排查看es STATISTICSINDEXes 之间的差异可能会有所帮助,这是帮助确定何时STATISTICS是更好选择的一种可能方法。

Thingy           PROs                             CONs
-------          ----------                       -------------------
INDEX            * Can help sorts.                * Takes up space.
                 * Contains data (can             * Needs to be maintained (extra I/O).
                   "cover" a query).              * More chances for blocking / dead-locks.

STATISTICS       * Takes up very little space.    * Cannot help sorts.
                 * Lighter maintenance / won't    * Cannot "cover" queries.
                   slow down DML operations.
                 * Does not increase chances
                   of blocking / dead-locks.

以下是我在寻找此资源时发现的一些资源,其中一些资源甚至问了同样的问题,但未得到回答:

SQL Server索引与统计

SQL Server统计信息问题我们不敢问

统计。多列直方图可能吗?

**明确地说,我对此没有答案,实际上我希望从一些人那里得到反馈,以在Internet上的此处提供似乎奇怪地缺少的信息。


1
索引将通过创建与表本身排序不同的查找来帮助SQL更快地找到数据。统计信息可帮助SQL确定满足查询所需的内存/工作量。
乔纳森·费特

@JonathanFite谢谢您的评论。我已将其纳入我的问题:)。
所罗门·鲁兹基

遵循@JonathanFite的评论,似乎统计数据最适合于提高即席系统/表/查询模式的性能,而索引最适合可预测的查询模式。我的意思是,这更多的是问题而不是陈述。
戴夫

Answers:


19

您的问题围绕着-仅创建统计信息还是创建索引(创建统计信息)何时是一件好事?

从我的sql server内部结构笔记(SQLSkills类IE1和IE2)和SQL Server内部结构书中,以下是我的有限理解:

SQL Server统计信息不过是包含有关索引键值和常规列值的重要信息的系统对象。

SQL Server使用基于成本的模型来尽可能快地选择“足够好”的执行计划。可伸缩性估计(估计查询执行的每个步骤中要处理的行数)是查询优化中最重要的因素,这反过来会影响联接策略,内存授予要求,工作线程选择以及访问数据时的索引选择。

当SQL Server估计较大的数字时,它将不使用非聚集索引。KEY或RID循环操作将是必需的,因此它将维护索引(和列)的统计信息,这将有助于此类估计。

关于统计信息,有2件重要的事情:

  1. 直方图仅存储有关最左侧统计信息(索引)列的数据分布的信息。它还存储有关键值的多列密度的信息。因此,从本质上讲,直方图仅存储最左侧统计信息列的数据分布。

  2. 无论表的大小如何,SQL Server最多将保留200个直方图步骤。随着表的增加,每个直方图步骤所覆盖的间隔也会增加,这会导致大型表的统计信息“准确性较低”。

    请记住,索引选择性是一个与密度成反比的度量,即列的唯一值越多,其选择性就越高。

当特定查询不经常运行时,您可以选择创建列级统计信息而不是索引。列级统计信息可帮助Query Optimizer查找更好的执行计划,即使由于涉及的索引扫描而使这些执行计划不理想。同时,统计信息不会在数据修改操作期间增加开销,并且有助于避免索引维护。此方法仅适用于很少执行的查询。

参考:

注意:诸如Paul WhiteAaron Bertrand之类的人可以发出声音,为您的好问题提供更多色彩。


“当SQL Server估计需要大量的KEY或RID循环操作时,它将不使用非聚集索引。”那么,QO是否可以独立于索引使用基于索引的stats对象?意思是,如果索引不是最佳的,但是查询中的前导列,则统计信息仍然相关。那么会使用它们吗?还是此信息暗示着在某些情况下不太可能使用索引,但是由于统计信息仍然有价值,因此没有真正的理由创建索引,只需统计信息即可?
所罗门·

8

我想说的是,当您需要能够根据字段限制数据量/快速获取正确的数据时,您需要一个索引。

当您需要优化器来了解数据的性质以便能够以最佳方式执行操作时,您需要统计信息。

我发现,过滤后的统计数据会在数据中的偏斜严重影响计划时提供帮助,例如,在堆栈溢出中,很少有用户拥有大量的帖子,因此仅使用每个用户的平均帖子并不是最佳的估计。因此,您可以基于用户名在userId上创建过滤的统计信息,然后SQL Server应该知道,当该用户名出现在查询中时,这就是它将获得的用户ID,并且应该能够弄清楚posts表中的索引字段将具有该id的大量行,因为在那里存在直方图。使用平均值,是不可能做到的。


1
嗨,谢谢你的回答。因此,什么时候我需要/希望优化器更好地理解数据的本质,而不是限制该数据或不想更快地获取它,或者需要它“覆盖”查询?与您的过滤索引示例相同。我确实得到了您说的从平均值中打破边缘情况的说法,但是为什么过滤后的统计数据比在相同字段上的过滤索引更好?这是我要达到的目标。
所罗门·鲁兹基

像在示例中一样,您无法在用户名上创建到posts表的过滤索引,因为该索引在该表中不存在。您可以根据用户ID创建它,但这不在where子句中。
James Z

但是即使不在时也不会UserID处于JOIN条件WHERE?而且那还不够好以获取筛选后的索引吗?
所罗门·鲁茨基

@srutzky在最新版本中可能更有可能,但是总的来说,我不会依赖...在大多数情况下,谓词必须完全匹配。我忘记了他们是否解决了这个问题,但是在某一时刻,WHERE BitColumn = 0对于简单的查询,不会选择过滤索引WHERE BitColumn <> 1。(并且要明确,bit列不可为空。)我认为有类似IntColumn > 10不匹配的情况IntColumn >= 11
亚伦·伯特兰

如果下次有人使用该计划时,将无法使用过滤索引。我认为没有任何可以使用过滤索引的联接。甚至无法使用变量,因为下次该值可能不合适。
James Z

4

来自Itzik Ben-Gan的70-461培训书

手动创建统计信息只有几个可能的原因。一个示例是查询谓词包含具有跨列关系的多个列时。多列的统计信息可以帮助改善查询计划。多列统计信息包含跨列密度,这在单列统计信息中不可用。但是,如果列已在同一索引中,则多列统计信息对象已经存在,因此您不应手动创建其他列。


感谢您发布此信息。这回答了我的部分问题,但仍然悬而未决:如果我需要多列统计信息,为什么我只创建STATISTICS而不是Index,索引将包含STATISTICS以及可以进一步帮助查询的其他信息( ies)?
所罗门·鲁兹基

1
我认为Kin的解释将进一步解释您的追求。也许经常插入但很少查询的堆?
健太郎
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.