高性能分页的常见解决方案是使用索引字段,从上一页的最后一个值开始每个新的“页”。例如,对于像这样的数据集(假设类别和ID是主键):
Category | ID | Name
Red | 10 | Bob Jones
Red | 14 | Sam Smith
Red | 16 | Jill White
Blue | 10 | Mike Green
Blue | 16 | Mary Brown
如果要返回所有Red
类别记录(假设ORDER BY类别,ID),则假设页面大小(较小)为1,
SELECT * FROM table WHERE Category='Red' AND ID>'00' (1st page, returns Bob Jones)
SELECT * FROM table WHERE Category='Red' AND ID>'10' (2nd page, returns Sam Smith)
SELECT * FROM table WHERE Category='Red' AND ID>'14' (3rd page, returns Jill White)
之所以可行,是因为通过分页,“键集”仅使用ID字段(如果ID全局唯一,则它也可以在多个字段上使用,而不是)。
但是,如果我想返回所有红色和蓝色记录(假设该表还包含其他类别),则一次仍要一页(假设ORDER BY Category,ID):
SELECT * FROM table WHERE Category IN ['Red', 'Blue'] AND Category>'' AND ID>'00' (1st page, returns Bob Jones)
SELECT * FROM table WHERE Category IN ['Red', 'Blue'] AND Category>'Red' AND ID>'10' (2nd page, returns Sam Smith, but skips Mike Green)
在PostgreSQL和其他一些语言中,有一种支持这种格式的“行值”谓词语法(假定ORDER BY Category,ID):
SELECT * FROM table WHERE (Category, ID) > ('', '00') (1st page, returns Bob Jones)
SELECT * FROM table WHERE (Category, ID) > ('Red', '10') (2nd page, returns Sam Smith)
之所以起作用,是因为出于测试目的,类别和ID都被视为单个复合值。但是我没有使用PostgreSQL或支持“行值”的数据库。因此,问题是是否有替代解决方案对此适用(无论是2个字段还是n个字段)?为了使其能够在多个变量字段上进行分页,我需要使用一个谓词,该谓词将始终以多字段排序顺序查找“下一条记录”。
PS:当然可以使用OFFSET / LIMIT或SKIP / LIMIT分页,但是对大数据集都不有效,这就是为什么我要使用“ keyset”分页。
答案 0 :(得分:1)
在The Impaler's answer上进行扩展,使用复合键的键集分页的通用语法如下:
WHERE
(x > a) OR
(x = a AND y > b) OR
(x = a AND y = b AND z > c) OR
...
了解结构并不那么复杂。当然,它不如(x, y, z) > (a, b, c)
好,但是您可以使用自己选择的语言对此进行编程。您只需要遍历一组字段,每个连续的字段都会扩展为包含先前字段中的{field} = {value} AND
。
答案 1 :(得分:0)
您始终可以对谓词进行措辞:
(x, y) > (a, b)
为:
x >= a and (x = a and y > b or x > a)
请注意,第一个前置x >= a
会促进(但不能确保)该列上索引的使用。即,它成为“访问谓词”。第二个x = a and y > b or x > a
过滤掉多余的行,有效地成为“过滤谓词”。
这种表述“元组不等式”谓词的方式促进了索引的使用。但是,如果您比较3、4或更多列,它们将变得越来越复杂。