Queryable.OrderBy 服务器数据库 SQL 不稳定吗?

Is Queryable.OrderBy unstable for SQL Server database?

OrderBy is stable for LINQ to Objects, but MSDN on Queryable.OrderBy 没有提到它是否稳定。

我想这取决于提供商的实施。 SQL服务器不稳定吗?因为它看起来如此。我快速浏览了 Queryable source code,但从那里看并不明显。

我需要在其他操作之前订购一个集合,为了性能我想使用 IQueryable,而不是 IEnumerable

// All the timestamps are the same and I am getting inconsistent 
// results by running it multiple times, first few pages return the same results
var result = data.OrderBy(i => i.TimeStamp).Skip(start).Take(length);

但如果我使用

var result = data.ToList().OrderBy(i => i.TimeStamp).Skip(start).Take(length);

它工作得很好,但我失去了从 LINQ 到 SQL 的性能提升。似乎 Queryable OrderBy/Skip/Take 的组合会产生不一致的结果。

SQL 生成的代码对我来说似乎没问题:

SELECT 
...
FROM [dbo].[Table] AS [Extent1]
ORDER BY [Extent1].[TimeStamp] ASC
OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY 

在 Linq-to-Entities 中,LINQ 查询被翻译成 SQL 查询,因此 OrderBy 的 Linq-to-Objects 实现无关紧要。您应该查看 ORDER BY 的数据库实现。如果您使用的是 MS SQL,您可以在文档中找到:

To achieve stable results between query requests using OFFSET and FETCH, the following conditions must be met: (...)

  1. The ORDER BY clause contains a column or combination of columns that are guaranteed to be unique.

所以相同值的 ORDER BY 不能保证相同的顺序,因此限制它可能会提供不同的结果集。要解决这个问题,您可以简单地按一些具有唯一值的附加列进行排序,例如ID。所以基本上你会有:

var result = data
    .OrderBy(i => i.TimeStamp)
    .ThenBy(i => i.Id)
    .Skip(start)
    .Take(length);

我认为 "stable" 是指一致。如果您在 SQL 查询中没有 ORDER BY,则无法保证每次 运行 查询时数据的顺序。它会简单地 return 所有数据,以对服务器最有效的顺序排列。当您添加 ORDER BY 时,它将对该数据进行排序。由于您正在对所有排序值都相同的数据进行排序,因此不会对任何行进行重新排序,因此已排序数据的顺序与您预期的不同。如果您需要特定的顺序,则需要添加辅助排序列,例如 ID。

最好不要假定从服务器返回的数据的顺序,除非您明确定义该顺序。