1

嗨,我有一个包含实体的表,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 不会总是工作......有什么想法吗?我需要订购吗?

4

1 回答 1

0

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

为了展示它,这是一个小测试 - 假设我们有这样的表格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,并且由于您没有指定 outer 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如果您的选择之间发生了一些数据修改,即使在最外层查询中指定也无法工作。

于 2013-09-18T12:13:00.370 回答