#create table to store sequences
CREATE TABLE seq (
seq_no int not null auto_increment,
id int not null,
primary key(seq_no),
unique(id)
);
#create the sequence
TRUNCATE seq;
INSERT INTO seq (id) SELECT id FROM mytable ORDER BY id;
#now get 1000 rows from offset 1000000
SELECT mytable.*
FROM mytable
INNER JOIN seq USING(id)
WHERE seq.seq_no BETWEEN 1000000 AND 1000999;
6条答案
按热度按时间4sup72z81#
也许您可以创建一个索引表,提供与目标表中的键相关的顺序键。然后您可以将此索引表联接到目标表,并使用where子句更有效地获取所需的行。
ycl3bljg2#
如果记录很大,则加载数据可能会很慢。如果ID列已建立索引,则只需选择它就会快得多。然后,可以使用IN子句执行第二次查询,以获得相应的ID(或者可以使用第一次查询中的最小和最大ID来制定WHERE子句)。
慢:
快速:
cnwbcb6i3#
互联网上有一篇博客文章,介绍了如何最好地使要显示的行的 * 选择 * 尽可能紧凑,因此:只有身份证并且生成完整的结果应该反过来获取您想要的所有数据 , 仅用于您选择的行 *。
因此,SQL可能是这样的(未经测试,我不确定它是否真的有用):
如果您的SQL引擎太原始而不允许使用这种SQL语句,或者它没有改进任何东西,那么可能值得将这个语句分解为多个语句,并将id捕获到数据结构中。
更新:我找到了我谈论的博客文章:是杰夫·阿特伍德在《编程恐怖》里的"All Abstractions Are Failed Abstractions"
nlejzf6q4#
我认为如果你的表已经有了一个单独的索引,就没有必要再创建一个单独的索引了。如果是这样,你可以通过这个主键来排序,然后使用这个键的值来逐步执行:
另一种优化方法是不使用SELECT * 而只使用ID,这样它就可以简单地读取索引,而不必定位所有数据(减少IO开销)。如果您需要其他一些列,那么也许可以将它们添加到索引中,以便使用主键读取它们(这将最有可能被保存在内存中,因此不需要光盘查找)-虽然这将不适合所有情况,所以你将不得不有一个发挥。
xpcnnkqh5#
Paul狄克逊的答案确实是这个问题的解决方案,但是您必须维护序列表并确保没有行间隙。
如果这是可行的,更好的解决方案是确保原始表没有行间隙,并从id 1开始,然后使用id获取行进行分页。
SELECT * FROM表格A,其中id〉= 1且id〈= 1000;
SELECT * FROM表格A,其中id〉= 1001且id〈= 2000;
等等...
q35jwt9p6#
我最近遇到了这个问题。这个问题有两个部分需要解决。首先,我必须在FROM子句中使用一个内部select,它只对主键进行限制和偏移:
然后,我可以使用它作为查询的from部分:
第一次创建这个查询时,我使用了MySql中的OFFSET和LIMIT。这个功能一直很好,直到我到达第100页后,偏移量开始变得慢得无法忍受。在我的内部查询中将其更改为BETWEEN,可以加快任何页面的偏移量。我不知道为什么MySql没有加快OFFSET,但BETWEEN似乎又把它卷回来了。