ret*_*ala 3 sql-server t-sql top
我正在尝试编写一个有效的查询来删除数据块。为此,我希望通过使用主键来获取最旧的记录来避免索引扫描。但是,我看到返回了一些意想不到的结果。
我希望这个
SELECT TOP 15 OrderID FROM [Order]
Run Code Online (Sandbox Code Playgroud)
会给我最旧的 15 条记录,因为我可以依靠主键递增,因此表中的存储顺序将从低到高。
但是,这会返回不同的结果集
SELECT TOP 15 OrderID FROM [Order] ORDER BY DateCreated ASC
Run Code Online (Sandbox Code Playgroud)
这似乎是获得我需要的结果的更准确但更昂贵的方式。
令人费解的是,这
SELECT TOP 15 * FROM [Order]
Run Code Online (Sandbox Code Playgroud)
为此提供一组不同的 OrderID (PK)
SELECT TOP 15 OrderID FROM [Order]
Run Code Online (Sandbox Code Playgroud)
我知道http://msdn.microsoft.com/en-gb/library/ms189463.aspx解释说没有 ORDER BY 子句就不能保证订单,但期望 PK 为我订购并且无法解释两者之间的差异最后两个选择子句。
Aar*_*and 11
看看计划。当您使用SELECT *
它时,可能会使用聚集索引,而当您只需要一列时,也许可以使用更薄的索引。
不要“期望”某个顺序。如果您不告诉 SQL Server 如何订购,那么它将使用最有效的方式,这可能会因 20 多个因素而改变。
如果您想要某个订单,请说。请在此处阅读 #3:
此外,Michael Swart 的这篇文章可能很有趣:
如果您希望您的第二个查询更有效,您可以考虑创建一个索引DateCreated
(您可能想要包括OrderID
- 不确定当前的索引结构)。
对于n
一次删除行的实际目标,首先删除最旧的行,并假设OrderID
是一IDENTITY
列(因此订单创建日期应大致与此一致),为什么不使用这种方法(基于这篇很棒的博客文章,也是由 Michael Swart 撰写的):
-- pick a datetime for the newest row you want to delete
-- let's say you want to delete all orders before Jan 1 2014:
SELECT @MaxOrderID = MAX(OrderID)
FROM dbo.[Order] -- terrible table name, also always use dbo prefix
WHERE DateCreated < '20140101';
DECLARE @BatchSize INT = 1000,
@LargestOrderProcessed INT = -1,
@NextBatchMax INT,
@RC INT = 1;
WHILE (@RC > 0)
BEGIN
SELECT TOP (@BatchSize) @NextBatchMax = OrderID
FROM dbo.[Order]
WHERE OrderID > @LargestOrderProcessed
AND OrderID <= @MaxOrderID
ORDER BY OrderID;
DELETE dbo.[Order]
WHERE OrderID > @LargestOrderProcessed
AND OrderID <= @NextBatchMax;
SET @RC = @@ROWCOUNT;
SET @LargestOrderProcessed = @NextBatchMax;
END
Run Code Online (Sandbox Code Playgroud)
为了尽量减少对日志的影响,您可能希望在其中添加一些额外的逻辑,来自我的博客文章Break large delete operations into chunks。至于dbo
前缀,请参阅要踢的坏习惯:避免使用架构前缀。
归档时间: |
|
查看次数: |
2327 次 |
最近记录: |