【问题标题】:Changed order of rows from same table更改同一表中的行顺序
【发布时间】:2015-05-30 20:57:37
【问题描述】:

我的情况很复杂。有一个父数据库P,然后还有另一个数据库C,我被告知它与P 相同(都是SQL Server 2012)。他们都在不同的服务器上。我正在对PC 进行select * from tableA。检索到的数据完全相同,但顺序不同。这两个表具有相同的元数据。可能的原因是什么?

编辑 1

问题是,我有一个从客户那里得到的存储过程,它在P 上运行,然后在 SSRS 报告中使用。我无权访问P 或报告。我在C 上运行相同的存储过程。那是当我得到相同的行但顺序不同的时候。除了已经存在的那些之外,没有在运行C 的存储过程中添加其他order by 子句。如果数据库相同,数据相同,表结构也相同,为什么行的顺序不同?

编辑 2

tableA

COL1       COL2       COL3       COL4
---------- ---------- ---------- ----------
100        C          1          2015-01-01
101        A          2          2015-01-05
102        A          2          2014-01-01
103        B          4          2011-09-01
104        C          1          2015-01-01

如果在上面tableACOL1PRIMARY KEY),我做一个select * from tableA order by COL2, COL3, COL4,那么:

P中的结果

COL1       COL2       COL3       COL4
---------- ---------- ---------- ----------
102        A          2          2014-01-01
101        A          2          2015-01-05
103        B          4          2011-09-01
100        C          1          2015-01-01
104        C          1          2015-01-01

C中的结果

COL1       COL2       COL3       COL4
---------- ---------- ---------- ----------
102        A          2          2014-01-01
101        A          2          2015-01-05
103        B          4          2011-09-01
104        C          1          2015-01-01
100        C          1          2015-01-01

这就是问题所在。

PS - 数据库的排序规则发生了变化

【问题讨论】:

  • 是的,在 COL2 上有一个订单,它们都在 COL2 上订购,因此订单是 AABCC,如果你想让它们相同,那么你需要在 order 子句中添加另一个列。在这种情况下,它将是 COL1,因为这是您的样本数据的唯一区别。就像这里的许多答案所指出的那样,即使一切都相同,也不能保证 SQL Server 中行的顺序,除非您指定它。

标签: sql sql-server-2012


【解决方案1】:

即使两个表具有相同的元数据;根据您的帖子,可以看出您没有在查询中使用ORDER BY 子句,也没有使用ORDER BY;返回结果的顺序永远无法保证。

即使您在同一服务器上多次运行查询,您也可能会观察到结果输出中的数据顺序不同。

为确保获取特定订单始终使用order by clause 以及您的查询

select * from tableA order by some_column

【讨论】:

  • @BhupeshC,这正是答案中所说的;没有order by,订单永远无法保证。如果可以保证订单,则不需要order by 实现。如果您有权访问在P 上运行的报告/程序;多次运行proc,结果数据的顺序根本不一样。
  • 如果您愿意,可以在您的问题中发布过程代码正文。
  • sp 中已经指定了order by 子句。该报告已在P 上运行多次。顺序不会改变。在C 上运行它时,它也不会更改为已经出现在C 上的内容。请参阅我的编辑了解更多信息。
  • order by COL2, COL3, COL4 正在做它应该做的事情。只有PK列COL1的顺序不同。如果您在两台机器上都执行order by col1 会怎样?如果可行的话,你能把你的表模式发布一次吗?
  • 目前我无法在P 中进行此操作,但我正在努力尝试。关键是,当我 order by 除 PK 之外的任何其他列时,尽管相似,但如果我在 P 上运行查询,COL1 的顺序与显示的顺序不同。
【解决方案2】:

除非您为您的表格指定PRIMARY KEY,否则您的数据的列出顺序严格来说不会被定义。在 MSSQL 中,通常有一个“内部”顺序,每个表似乎都可以重现,但是,正如您所观察到的,对于两个不同服务器上的“相同”表,这可能会有所不同。如果您想在两台服务器上为表建立相同的顺序,您应该:

  • 引入主键
  • 或始终使用selectorder by

【讨论】:

  • 主键——甚至不是集群主键——保证没有order byselect集合的顺序。结果集是无序的,除非ORDER BY 子句指定了排序。你可能会觉得这篇文章很有趣:dba.stackexchange.com/questions/19203/….
【解决方案3】:

正如其他答案中所说,除非您指定 order by,否则 SQL Server 可以并且很可能以任意顺序返回结果。实际原因是实现细节,取决于 SQL Server 在编译查询时使用的查询优化决策。

试试这个。在返回结果的查询末尾添加查询提示option (maxdop 1)。然后尝试对两个数据库进行查询。结果是否以相同的顺序返回?

这个query hintforces the SQL Server optimizer to avoid parallelism。如果 SQL Server 计算查询的巨大成本,它可能会选择并行运行查询(取决于 MAXDOP 服务器选项和查询提示)。当查询并行运行时,不同的线程可能会先于其他线程提供结果,并且每次运行时结果的顺序可能不同。

如果没有order by 子句,查询顺序也可能取决于查询计划。任何影响查询计划的事情都会影响查询顺序。这方面的一个例子是parameter sniffing。例如,查询select * from [Addresses] where [Country] = 'Luxembourg'。此查询可能会使用索引查找和书签查找来返回结果,因为与地址数量相比,卢森堡的人口相当少。这可能会导致行按[Country] 索引排序。

现在clear the procedure cache 并尝试'select * from [Addresses] where [Country] = 'China'。此查询可能使用表扫描,因为该查询返回所有列,并且扫描表可能比针对[Country] = 'China' 执行索引查找然后执行bookmark lookup 更便宜。此查询可能按磁盘上数据的物理顺序排序。除非您指定 order by 子句,否则无法保证。

更新

您提供了示例查询和架构。 order by COL2, COL3, COL4 子句将保证结果按这 3 列排序。但是,如果这 3 列中有重复值,则不能保证这些行以一致的顺序返回。如果这对您很重要,则必须修改 order by 子句以包含主键。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-22
    • 1970-01-01
    相关资源
    最近更新 更多