您无法知道给定页面上的第一个ID是什么,因为ID号码不一定是顺序的。换句话说,序列中可能存在空白,所以100行的第五页上的行不一定从id 500开始。它可以以id 527开始,例如,不可能知道。
换言之另一种方式:ID是一个值,而不是行号。
如果你的客户是通过以升序页推进一个可行的办法是,每个REST请求获取数据,指出值页面上的最大 ID,然后使用该在下一个 REST请求,以便它查询id值较大。
SELECT ... FROM ... WHERE filterKey = filterValue
AND id > id_of_last_match_of_previous_page
但是,如果您的REST请求可以获取任意随机页面,则此解决方案不起作用。这取决于已经获取了先前的页面。
另一种解决方案是使用LIMIT <x> OFFSET <y>
语法。这使您可以请求任何任意页面。 LIMIT <y>, <x>
的工作原理是相同的,但出于某种原因,x和y在两种不同的语法形式中是相反的,所以请牢记这一点。
使用LIMIT...OFFSET
在请求结果中包含多页的页面时效率不高。假设您要求第5,000页。 MySQL必须在5,000页的服务器端生成一个结果,然后丢弃其中的4,999个,并返回结果中的最后一页。对不起,但这是它的工作原理。
回复您的评论:
你必须明白,WHERE
适用于值行的条件,但网页是由行位置定义。这是确定行的两种不同方式!
如果您有一列保证为行号,那么您可以像使用行位置那样使用该值。您甚至可以在其上放置索引,或将其用作主键。
但是,主键值可能会更改,并且可能不连续,例如,如果更新或删除行或回滚某些事务等等。对主键值重新编号是一个坏主意,因为其他表或外部数据可能会引用主键值。
所以你可以添加另一列而不是的主键,但只有一个行号。
ALTER TABLE MyTable ADD COLUMN row_number BIGINT UNSIGNED, ADD KEY (row_number);
然后在需要对行重新编号时填写值。
SET @row := 0;
UPDATE MyTable SET row_number = (@row := @row + 1) ORDER BY id;
例如,如果您曾删除某些行,您将不得不重新编号行。经常这样做效率不高,取决于表格的大小。
另外,如果不锁定表格,新插入无法创建正确的行号值。这对于防止竞争条件是必要的。
如果您保证row_number
是一系列连续值,那么它既是一个值又是一个行位置,因此您可以将它用于任何任意行的页面的高性能索引查找。
SELECT * FROM MyTable WHERE row_number BETWEEN 401 AND 500;
至少直到下一次通过删除或新插入对行号序列置疑。
这似乎是一个非常奇怪的方式来做到这一点。在我的经验研究小型/中型数据集标准是为了通过行,这样就得到一个一致的数据集(这样你就可以使用任何WHERE),然后使用LIMIT和,位我怀疑你可能已经错过了,偏移子句告诉MySQL从位置X返回行。 –
过滤的数据集通常可能有多大? – Strawberry
乔恩 - 我明白了,我不熟悉OFFSET,谢谢。草莓 - 我希望能够一次获取200行的东西,从过滤的结果可以达到成千上万。 –