您好,我有一个包含实体的表,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
对于您最初的问题,如果您的选择之间发生了一些数据修改,即使在最外层查询中指定 order by
也无法正常工作。
关于sql - Postgres - 顺序的位置是否重要?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18871176/