sql - Postgres - 顺序的位置是否重要?

标签 sql postgresql limit offset

您好,我有一个包含实体的表,id 是从一个序列生成的

我的表中有超过 2mio 个条目,现在我想翻阅所有元素。但是

LIMIT 100 OFFSET 2000000

对我来说太慢了,所以我尝试了两种不同的语句(伪代码)

int i = 0;    
while(true) {
    a: SELECT * FROM entity WHERE id>=i ORDER BY id LIMIT 100 
    b: SELECT * FROM (SELECT * FROM entity ORDER BY id)a WHERE id>=i  LIMIT 100 
    i=<id of last fetched row>;
}

两个查询都很快并且似乎显示了正确的结果...但我预感到 a 不会总是有效...有什么想法吗?我需要订购吗?

最佳答案

是的,在您的查询位置 order by does matter。 AFAIK,在 SQL 规范中,如果您在最外层查询中未指定 order by,则根本无法保证结果集中行的顺序。有时您可以偶然得到所需的行,但不能保证。

为了展示它,这里是一个小测试 - 假设我们有这样的表 test:

create table test(id int, name text);

insert into test 
select 1, 'John' union all
select 2, 'Adele';

现在让我们运行一些查询。这个可以正常工作(由 order by 保证):

select * from test as t1 order by t1.name;

id    name
-----------
2     Adele
1     John

这个几乎可以肯定会很好地工作,它是从有序子查询中选择的,SQL 没有理由对其重新排序:

select * from (select * from test order by name) as t1

id    name
-----------
2     Adele
1     John

但是假设我们必须在这个查询中使用自连接。这个,同样,可以正常工作(由 order by 保证):

select *
from test as t1
    inner join test as t2 on t2.id = t1.id
order by t1.name;

id    name
-----------
2     Adele
1     John

但是这个会因为merge join而被重新排序。 SQL 必须在合并连接期间按连接的列对集合进行排序,因此它对 t1 进行了重新排序,并且由于您没有指定外部 order by,将返回按 id 排序的结果:

select *
from (select * from test order by name) as t1
    inner join test as t2 on t2.id = t1.id;

id    name
-----------
1     John
2     Adele

sql fiddle demo

对于您最初的问题,如果您的选择之间发生了一些数据修改,即使在最外层查询中指定 order by 也无法正常工作。

关于sql - Postgres - 顺序的位置是否重要?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18871176/

相关文章:

mysql - 按类别中项目的下载次数对类别进行排序

sql left join with where混淆

sql - 永远更新查询

MySQL - 来自一个查询的两条记录集,具有不同的顺序和限制

http - 有没有办法在 Tornado 中设置上传文件大小限制?

c - OpenGL GLint,GLsizei 限制?

php - Mysql 没有将时间戳转换为 PHP 查询的时区

SQL/Presto 将列表列扩展为多行

oracle - 将 SPATIAL 数据从 Oracle 迁移到 Postgresql

postgresql - 在 PostgreSQL 中增加共享缓冲区的缺点是什么