当没有提供ORDER BY时,Postgres如何对结果进行排序

10

假设我有两个表:

user (user_name varchar(50), project_name varchar(50))
project (project_name varchar(50), project_cost(integer))

我有一个查询,返回的结果是“事实上所需的”:

select u.user_name, p.project_name 
from user u, project p 
where u.project_name = p.project_name

Postgres表示在没有提供ORDER BY时,行的顺序是不可预测的。但是在我的本地测试中,Postgres返回相同顺序的行用于重复测试。

请问您能帮我理解当查询中未提供order by时,Postgres到底做了什么吗?

由于我无法访问所有可能存在真实表和架构的地方,因此我真的需要知道发生了什么以保持现有的排序不变。

3个回答

15

如果没有给出order by子句,Postgres(以及其他任何合理的数据库)应该按照它能够产生它们的顺序返回行(无论是来自内部缓存、索引还是直接来自表格)。

由于相同的算法在相同的数据上使用,因此你得到的行以相同的顺序返回并不奇怪。然而,这并不意味着你应该依赖这个排序方式。如果你对数据的布局进行了改变(例如备份并还原它,或者甚至重建表的索引),你很可能会得到不同的排序。


排序规则或字符集是否在这里起作用?还是这些设置仅影响使用order by对列进行排序时? - Mecon
如果数据是从索引中检索出来的,那么它本质上是以排序方式存储的,因此排序规则可能会发挥作用。 - Mureinik
谢谢。我想我得找出符合业务逻辑的排序顺序,并明确添加它。 - Mecon
3
@Mecon: 您甚至不需要对数据进行任何操作。Postgres有一个名为“同步序列扫描”的特性,它意味着一个查询可以重复使用正在运行的表上的seq-scan,即使在中途。这意味着两个同时执行的SELECT语句可能会以完全不同的顺序返回数据,即使磁盘上没有任何更改并且两者都使用相同的执行计划。 - user330315

2
要了解DBMS的真正作用,应该看计划。输出顺序也将取决于此。但是有两件事要记住:首先,如果计划包括“完整(堆)表扫描”,则顺序未定义(因为DBMS可以自由地重新排序堆数据);其次,如果更改SQL语句或更新DB统计信息,则计划可能会发生重大变化。这就是为什么您不应该长期依赖输出顺序的稳定性。

1
如果没有order by,则顺序始终未定义。没有执行计划会改变这一点。 - user330315
1
@a_horse_with_no_name 不完全是这样。有些计划隐含地定义了顺序,有些则没有。但问题在于,有时候很难(甚至不可能)在没有“order by”的情况下实现所需的顺序,而修复计划比添加“order by”更容易。 - Matt

0

如果表有聚集索引,那么可能是按照聚集索引的顺序。但是这不是可以信任的事情,因为文档上是这样说的。


1
Postgres没有聚集索引。 - user330315
抱歉,我在想SQL Server。 - Zohar Peled
@a_horse_with_no_name Postgres有这个CLUSTER命令:http://www.postgresql.org/docs/9.4/static/sql-cluster.html。这不是同样的东西吗? - Mecon
3
@Mecon:不,它与聚集索引不同。 - user330315

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接