我正在尝试编写一个有效的查询来删除数据块。为此,我希望通过使用主键来获取最旧的记录来避免索引扫描。但是,我看到返回了一些意想不到的结果。
我希望这个
SELECT TOP 15 OrderID FROM [Order]
会给我最旧的 15 条记录,因为我可以依赖主键递增,因此表中的存储顺序从低到高。
但是,这会返回不同的结果集
SELECT TOP 15 OrderID FROM [Order] ORDER BY DateCreated ASC
这似乎是一种更准确但更昂贵的方式来获得我需要的结果。
令人困惑的是,这
SELECT TOP 15 * FROM [Order]
为此提供一组不同的 OrderID (PK)
SELECT TOP 15 OrderID FROM [Order]
我了解http://msdn.microsoft.com/en-gb/library/ms189463.aspx解释说,如果没有 ORDER BY 子句,则无法保证订单,但希望 PK 为我订购,无法解释两者之间的差异最后两个选择子句。
看看计划。当您使用
SELECT *
它时,可能会使用聚集索引,而当您只想要一列时,可能会使用更精简的索引。不要“期望”某个顺序。如果您不告诉 SQL Server 如何订购,那么它将使用最有效的方式,这可能会因可能超过 20 个因素而改变。
如果您想要某个订单,请说。请在此处阅读#3:
此外,Michael Swart 的这篇文章可能很有趣:
如果您希望您的第二个查询更有效率,您可以考虑创建一个索引
DateCreated
(您可能想要包括OrderID
- 不确定当前的索引结构)。对于您
n
一次删除行的实际目标,首先删除最旧的行,并假设OrderID
是一IDENTITY
列(因此订单创建日期应该大致与之一致),为什么不使用这种方法(基于这篇很棒的博客文章,也是 Michael Swart 的):为了尽量减少对日志的影响,您可能需要在其中添加一些额外的逻辑,来自我的博客文章Break large delete operations into chunks。至于
dbo
前缀,请参阅要踢的坏习惯:避免使用架构前缀。