order by
子句的select
语句应被视为没有特定的排序。但实际上在SQL Server和Oracle中(我已在这两个平台上进行了测试),如果我从一个没有order by
子句的表中多次查询,我总是会以相同的顺序获得结果。这种行为可靠吗?有人能帮忙解释一下吗?order by
子句的select
语句应被视为没有特定的排序。但实际上在SQL Server和Oracle中(我已在这两个平台上进行了测试),如果我从一个没有order by
子句的表中多次查询,我总是会以相同的顺序获得结果。这种行为可靠吗?有人能帮忙解释一下吗?select * from foo_table
这样简单的查询可能会按照存储在磁盘上的顺序返回,可能是按照主键顺序或创建顺序或其他随机顺序。更复杂的查询,比如 select * from foo where bar < 10
,可能根据索引读取以不同列的顺序返回,或者根据表的顺序返回用于表扫描。更加复杂的查询,包括多个where
条件、group by
子句、union
操作,将按照规划器确定的最有效生成顺序生成。ORDER BY
子句,你就没有准确地要求特定的顺序,因此RDBMS将按照RDBMS预计能够最快生成数据的算法给你返回这些行,并以某种偶然的查询方面对应的方式排序。ORDER BY
子句。如果您关心顺序而不关心效率,请使用ORDER BY
子句。如果你真的关心两个方面,就使用ORDER BY
,并仔细调整你的查询和数据库,使其更加高效。
ORDER BY
的另一个原因是 SQL Server Enterprise Advanced Scan,也称为 Merry-Go-Round Scan。 (在 Dmitri Korotkevitch 的优秀著作《Pro SQL Server Internals》中提到) - Grzegorz Smulko为了获得可预测的结果,应该使用ORDER BY
。 即使如此,在指定列中有相同的值时,你也可能会得到不同的结果。你可能需要按照你并不认为必要的字段来排序,以获得可预测的结果。
这是一个新的回答,用来纠正旧的回答。我从Tom Kyte那里得到了答案,并在此发布:
如果您想要对行进行排序,必须使用ORDER BY。没有任何条件或者例外,绝对如此。http://tkyte.blogspot.ru/2005/08/order-in-court.html 您需要在IOT上使用order by。行在叶块中排序,但是叶块不按排序存储。快速完整扫描=未排序的行。
https://twitter.com/oracleasktom/status/625318150590980097
https://twitter.com/oracleasktom/status/625316875338149888
(注意!以下原问题的答案仅用于历史记录,是错误的答案。正确答案在上面)
正如Tom Kyte在之前提到的文章中所写:
您应该将堆有序表视为一个大的无序行集合。这些行将以看似随机的顺序出现,并且取决于使用的其他选项(并行查询、不同的优化器模式等),它们可能在相同的查询下以不同的顺序出现。除非您在查询中有ORDER BY语句,否则永远不要指望从查询中获取行的顺序!
但请注意,他只谈到了堆有序表。但也有索引有序表。在这种情况下,您可以依赖选择的顺序而不需要ORDER BY
,因为顺序是由主键隐式定义的。这对于Oracle是正确的。
对于SQL Server聚集索引(索引有序表)默认创建。还有可能让PostgreSQL通过索引对齐存储信息。更多信息可以在这里找到。
更新:我发现我的答案被投票否决了。所以我会尝试解释一下我的观点。 在索引有序表概述部分,有这样一句话:
在索引有序表中,行存储在定义在表的主键上的索引中... 当相关数据必须一起存储或数据必须按特定顺序物理存储时,索引有序表非常有用。
http://docs.oracle.com/cd/E25054_01/server.1111/e25789/indexiot.htm#CBBJEBIH
由于索引的存在,所有数据都按特定顺序存储,我相信Pg也是如此。 http://www.postgresql.org/docs/9.2/static/sql-cluster.html 如果您不同意我的看法,请给我提供文档链接。我很乐意知道有什么可以学习的。
ORDER BY
有什么意义呢?这些按键真的值得为可预测性而交换吗? - Aaron Bertrand