【问题标题】:MSSQL: Why is this index 10 times faster than the other one?MSSQL:为什么这个索引比另一个快 10 倍?
【发布时间】:2014-07-13 14:37:09
【问题描述】:

我发现了一个非常奇怪的行为,我必须对此进行解释。我们有一个包含大约 450.000 个条目的简单表 (MSSQL 2008 R2)。

这个表的索引很简单:

索引 #1 包含:

[OwnerUserID] -> int, 4 byte
[TargetQuestionID] -> int, 4 byte
[LastChange] -> date,  8 byte

索引 #2 包含:

[LastChange] is a date, 8 byte
[OwnerUserID] is an int, 4 byte
[TargetQuestionID] is an int, 4 byte

如您所见,区别仅在于列的顺序略有不同;在两个索引中,叶子的大小相同,均为 16 字节(与我在大型数据库上执行某些 DBA 时所看到的相差甚远)

查询很简单:

Query #1:
- Asks just for the last entried element ( top(1) ) ordered by LastChange, so it takes only LastChange into account

Query #2:
- Asks just for the last entried element ( top(1) ) entried for a distinct OwnerUserID, so it takes OwnerUserID and LastChange into account

结果是:

查询 #1 的索引 #1 非常慢,尽管我认为它应该没问题,因为数据叶真的不大(16 字节)

查询 #2 的索引 #2 非常慢(但由于它考虑了两个值,OwnerUserID + LastChange = 8 个字节,我看不出它应该慢得多/快得多的任何原因)

我们的想法是只有一个索引,但由于每个查询场景的性能相差 10 到 11 倍,我们最终只并行创建了这两个索引,我们认为我们可以使用一个 - 因为index 并没有那么大/复杂,以至于您实际上会认为列顺序的这种细微差别会受到伤害。

所以,现在我们浪费了两倍的空间,而且由于表每天大约增长 10k 行,我们将来会在某个地方遇到磁盘空间问题......

首先,我认为这是由于 NHibernate 的一些内部问题,但我们检查了性能监视器,结果绝对可以重现。

似乎带有索引的 MSSQL 性能很大程度上取决于日期时间列的使用,因为这个简单的示例表明这可能会导致整个性能崩溃:-/

【问题讨论】:

  • 检查执行计划。
  • 呵呵,没错——我们只检查了 SQL 分析器来查看它需要多长时间,而不是执行计划:-/

标签: sql sql-server performance nhibernate database-design


【解决方案1】:

通常使用索引来实现快速二进制搜索,而不是慢速顺序搜索。为了实现这一点,他们将索引键以排序顺序或树存储。但是只有在知道键的开始时才可能进行二分查找,因此元素的顺序很重要。在您的情况下,这意味着:

  • Query#1 需要 LastChange 最低的记录。此查询可以使用索引进行优化,该索引以 LastChange 开头,例如索引#2。使用 Index#1,它需要退回到顺序搜索。
  • Query#2 需要首先找到所有唯一的 OwnerId,并且以 OwnerId 开头的索引可以在这里提供帮助。然后它需要为特定的 OwnerId 找到最低的 LastChange。 Index#1 在这里不再有帮助,因为索引中的下一个字段不是 LastChange。如果同一个 OwnerId 有很多记录,索引#2 可能会有所帮助。否则它可能会进行顺序搜索。

所以对于索引,字段的顺序应该与查询匹配。此外,您可能需要更新您的统计信息,以便查询规划器知道是进行顺序搜索(每个 OwnerId 很少条目)还是使用 Index#2(每个 OwnerId 有很多条目)更好。我不知道这是否以及如何使用 mysql 来完成,仅从 postgresql 中知道。

索引始终是一种权衡:它会减慢插入速度,但会加快查询速度。因此,这在很大程度上取决于您的应用程序有多少索引以及它们将如何构建。

【讨论】:

  • 补充:使用您拥有的工具而不是提问。查看查询计划 - 他们会很乐意向您展示使用了哪些索引。 Management Studi 可以很好地对其进行可视化。
  • TomTom,如上所述:好主意 - 我们没有检查执行计划,只有 SQL Profiler...
猜你喜欢
  • 1970-01-01
  • 2015-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多