我的表(SQL Server 2008)有100万条记录,当我尝试按日期时间订购记录时,需要1秒钟,但是当我按ID(int)订购时,它只需要大约0.1秒。
有没有办法提高效率? (我已经将datetime列添加到索引中)
答案 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 Basics,General Index Design Guidelines,Nonclustered Index Design Guidelines或How 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设置为组合索引并设置簇为真。