【发布时间】: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