SQL可以使用ORDER BY为同一查询的两次运行返回不同的结果吗?

时间:2015-10-15 12:16:51

标签: sql sql-server sql-order-by

我有下表:

public int read(CharBuffer target) throws IOException
public int read(char[] cbuf) throws IOException
public abstract int read(char[] cbuf, int off, int len) throws IOException

CREATE TABLE dbo.TestSort ( Id int NOT NULL IDENTITY (1, 1), Value int NOT NULL ) 列可能(并且预计)包含重复项 我们还假设表中已有1000行。

我试图证明关于不稳定排序的观点。

鉴于此查询返回“'页面'前1000个插入结果的10个结果:

Value

我的直觉告诉我,如果SELECT TOP 10 * FROM TestSort WHERE Id <= 1000 ORDER BY Value 列包含重复值,则此查询的两次运行可能会返回不同的行。

我基于以下事实:

  • 排序不稳定
  • 如果在查询的两次运行之间在表中插入新行,则可能会创建B树的重新平衡(Value列可能会被编入索引)

编辑:为了完整性:我假设插入后的行永远不会改变,并且永远不会被删除。

相反,具有稳定排序的查询(按Id 排序)应始终返回相同的结果,因为Value是唯一的:

ID

问题是:我的直觉是否正确?如果是,您是否可以提供可产生不同结果的操作的实际示例(至少在您的机器上#34;&#34;)?您可以修改查询,在SELECT TOP 10 * FROM TestSort WHERE Id <= 1000 ORDER BY Value, Id 列上添加索引等 我并不关心确切的查询,而是关注原则。

我正在使用MS SQL Server(2014),但对任何SQL数据库的答案都同样满意。

如果没有,那么为什么?

3 个答案:

答案 0 :(得分:2)

你的直觉是正确的。在SQL中,order by的排序不稳定。所以,如果你有关系,他们可以按任何顺序返回。并且,订单可以从一次运行变为另一次运行。

documentation解释了这一点:

  

使用OFFSET和FETCH作为分页解决方案需要运行查询   返回客户端应用程序的每个“页面”数据一次。   例如,要以10行为增量返回查询结果,   您必须执行一次查询以返回第1行到第10行然后   再次运行查询以返回行11到20,依此类推。每个查询都是   独立且不以任何方式相互关联。这意味着,   与使用一次执行查询并且状态为的游标不同   维护在服务器上,客户端应用程序负责   跟踪状态。使用查询请求之间实现稳定的结果   OFFSET和FETCH,必须满足以下条件:

     
      
  • 查询使用的基础数据不得更改。也就是说,查询所触及的行不会更新或全部更新   来自查询的页面请求在单个事务中执行   使用快照或可序列化的事务隔离。更多   有关这些事务隔离级别的信息,请参阅SET   TRANSACTION ISOLATION LEVEL(Transact-SQL)。

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

  •   

虽然这具体指的是offset / fetch,但它明确适用于多次运行查询而没有这些子句。

答案 1 :(得分:1)

如果您订购订单时有联系不稳定。

<强> LiveDemo

CREATE TABLE #TestSort
(
Id INT NOT NULL IDENTITY (1, 1) PRIMARY KEY,
Value INT NOT NULL
) ;

DECLARE @c INT = 0;

WHILE @c < 100000
BEGIN
  INSERT INTO #TestSort(Value)
  VALUES ('2');

  SET @c += 1;
END

示例:

SELECT TOP 10 * 
FROM #TestSort 
ORDER BY Value
OPTION (MAXDOP 4);

DBCC DROPCLEANBUFFERS;  -- run to clear cache

SELECT TOP 10 * 
FROM #TestSort 
ORDER BY Value
OPTION (MAXDOP 4);

关键是我强制查询优化器使用并行计划,因此无法保证它将按顺序读取数据,就像没有涉及并行性时可能会执行Clustered索引一样。

除非您明确强制使用ORDER BY Id, Value以特定方式对结果进行排序,否则您无法确定查询优化程序将如何读取数据。

如需了解更多信息,请阅读 No Seatbelt - Expecting Order without ORDER BY

答案 2 :(得分:-1)

我认为这篇文章将回答你的问题:

Is SQL order by clause guaranteed to be stable ( by Standards)

当您处于单线程环境中时,结果是每次都相同。由于使用了多线程,因此无法保证。