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

sil*_*ent 23 sql sql-server sql-order-by sql-server-2008

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

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

Qua*_*noi 25

排序方式id可能使用一个聚集索引扫描,同时通过订购datetime既可使用排序或索引查找.

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

如果您的表是聚类的id,基本上它意味着它已经被排序.这些记录包含在一个B+Tree链接列表中,该链接列表按id顺序链接页面.引擎应该只遍历链表以获取所排序的记录id.

如果id按顺序插入s,则意味着行的物理顺序将与逻辑顺序匹配,并且聚簇索引扫描将更快.

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

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

要改进排序,您可以在以下位置创建单独的覆盖索引datetime:

CREATE INDEX ix_mytable_datetime ON mytable (datetime) INCLUDE (field1, field2, …)
Run Code Online (Sandbox Code Playgroud)

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

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

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

更新:

关于这个问题的新帖子:


Rem*_*anu 6

为了尊重ORDER BY引擎有两种选择:

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

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

考虑以下三个查询:

SELECT dateColumn FROM table ORDER BY dateColumn
SELECT * FROM table ORDER BY dateColumn
SELECT someColumn FROM table ORDER BY dateColumn
Run Code Online (Sandbox Code Playgroud)

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

MSDN 上将详细介绍该主题,请参阅索引设计基础,常规索引设计指南,非聚簇索引设计指南如何:优化SQL索引.

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

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