【问题标题】:Is Queryable.OrderBy unstable for SQL Server database?SQL Server 数据库的 Queryable.OrderBy 是否不稳定?
【发布时间】:2018-09-30 08:06:51
【问题描述】:

OrderBy 对于 LINQ to Objects 是稳定的,但 Queryable.OrderBy 上的 MSDN 没有提及它是否稳定。

我想这取决于提供者的实现。 SQL Server 不稳定吗?因为它看起来如此。我快速浏览了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 

【问题讨论】:

  • OrderBy 被转换为 SQL order by,因此它取决于数据库提供程序。
  • @arekzyla 数据库提供程序是 MS SQL。
  • 您是否检查了执行了哪些 SQL 查询?见stackoverflow.com/questions/18237312/…
  • @MarcinJuraszek 答案已更新

标签: c# entity-framework linq linq-to-sql iqueryable


【解决方案1】:

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

要在使用 OFFSET 和 FETCH 的查询请求之间获得稳定的结果,必须满足以下条件: (...)

  1. ORDER BY 子句包含保证唯一的列或列组合。

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

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

【讨论】:

  • 不错的答案! ThenBy 解决了这个问题。感谢您从 MS SQL 文档中删除行,很高兴知道这一点。
【解决方案2】:

我认为“稳定”是指一致。如果您在 SQL 查询中没有 ORDER BY,则每次运行查询时都无法保证数据的顺序。它只会以对服务器最有效的顺序返回所有数据。当您添加 ORDER BY 时,它将对该数据进行排序。由于您正在对所有排序值都相同的数据进行排序,因此不会重新排序任何行,因此已排序的数据处于您不期望的顺序。如果您需要特定的顺序,则需要添加二级排序列,例如 ID。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-30
    • 2012-02-16
    • 1970-01-01
    • 1970-01-01
    • 2012-06-03
    • 2020-08-16
    • 1970-01-01
    相关资源
    最近更新 更多