SQL Server 2008:按日期时间排序太慢

时间:2009-11-11 17:31:39

标签: sql sql-server sql-server-2008 sql-order-by

我的表(SQL Server 2008)有100万条记录,当我尝试按日期时间订购记录时,需要1秒钟,但是当我按ID(int)订购时,它只需要大约0.1秒。

有没有办法提高效率? (我已经将datetime列添加到索引中)

8 个答案:

答案 0 :(得分:25)

id排序可能使用聚簇索引扫描,而datetime排序则使用排序或索引查找。

这两种方法都比聚簇索引扫描慢。

如果您的表由id聚类,基本上它意味着它已经排序。记录包含在B+Tree中,其中包含以id顺序链接页面的链接列表。引擎应该遍历链表以获取id订购的记录。

如果按顺序插入id,这意味着行的物理顺序将与逻辑顺序匹配,聚集索引扫描将更快。

如果您希望按datetime订购记录,则有两种选择:

  • 从表中获取所有记录并对其进行排序。缓慢是显而易见的。
  • 使用datetime上的索引。索引存储在磁盘的单独空间中,这意味着引擎需要在嵌套循环中在索引页和表页之间穿梭。它也更慢。

为了改善排序,您可以在datetime上创建单独的覆盖索引:

CREATE INDEX ix_mytable_datetime ON mytable (datetime) INCLUDE (field1, field2, …)

,并将您在查询中使用的所有列包含在该索引中。

此索引类似于表的卷影副本,但数据按不同顺序排序。

这将允许摆脱键查找(因为索引包含所有数据),这将使datetime的排序速度与id上的排序速度一样快。

<强>更新

关于此问题的新博文:

答案 1 :(得分:6)

要遵守ORDER BY引擎有两种选择:

  • 使用提供请求订单的索引扫描行
  • 对行进行排序

第一个选项很快,第二个选项很慢。问题是,为了使用,索引必须是覆盖索引。这意味着它包含SELECT投影列表中的所有列以及WHERE子句中使用的所有列(至少)。如果索引未覆盖,则引擎必须查找每行的聚簇索引(即“表”),以便检索所需列的值。这种常量的值查找是昂贵的,并且当引擎(正确地)决定更有效地扫描聚簇索引并对结果进行排序时,存在一个转折点,实际上忽略了非聚集索引。有关详细信息,请参阅The Tipping Point Query Answers

考虑以下三个问题:

SELECT dateColumn FROM table ORDER BY dateColumn
SELECT * FROM table ORDER BY dateColumn
SELECT someColumn FROM table ORDER BY dateColumn

第一个将在dateColumn上使用非聚集索引。但是第二个不会在dateColumn上使用索引,可能会选择扫描并对1M行进行排序。另一方面,第三个查询可以从Table(dateColumn) INCLUDE (someColumn)上的索引中受益。

MSDN上详细介绍了此主题,请参阅Index Design BasicsGeneral Index Design GuidelinesNonclustered Index Design GuidelinesHow To: Optimize SQL Indexes

最终,表格设计中最重要的选择是您使用的聚集索引。几乎总是将主键(通常是自动递增的ID)保留为聚簇索引,这一决定只能使某些OLTP负载受益。

最后,一个相当明显的问题:为什么世界上你会订购100万行?你不可能展示它们,是吗?解释一下您的用例可能会帮助我们找到更好的答案。

答案 2 :(得分:2)

将日期时间添加到新索引中,将其添加到ID仍然无济于事。

答案 3 :(得分:1)

可能是你的int列有一个索引但是你的datetime列没有吗? 看看执行计划。

答案 4 :(得分:0)

可能如果您将datatime存储为int,但每次存储或获取数据时都需要时间转换。 (用于存储员工的常用技术,如IP地址,寻求时间更快)

你应该检查你的服务器如何存储日期时间,b / c它你的服务器已经将它存储为int或bigint ..它不会改变任何东西....

答案 5 :(得分:0)

如果您的datetime字段包含许多不同的值且这些值很少更改,请在datetime字段上定义聚簇索引,这将按日期时间值对实际数据进行排序。有关使用聚簇索引的信息,请参阅http://msdn.microsoft.com/en-us/library/aa933131(SQL.80).aspx

这会使你的搜索速度变慢,因为它们将被降级为使用非聚集索引。

答案 6 :(得分:0)

您是否已将DateTime字段添加到“the”索引或独占索引?您是否按照其他字段和DateTime过滤您的选择,还是仅过滤此选项?

您必须拥有一个索引,其中包含您要过滤的所有字段,并且最好采用相同的顺序来优化性能。

答案 7 :(得分:0)

在某些情况下,您可以将日期时间设置为集群索引,如果您的表的主键不重要,例如用户日志表,您可以设置主键不集群,然后将时间和用户ID设置为组合索引并设置簇为真。