基于products表的Keyset/Seek分页及多条件筛选(获取第二页)
多条件筛选 + Keyset/Seek 分页实现指南
嘿,我来给你详细拆解怎么用Keyset/Seek分页实现产品的多条件筛选,同时获取第二页(每页10条)的数据。先从你给出的Offset分页方案说起,再对比着讲Keyset的正确姿势。
先回顾你提供的Offset分页实现
Offset分页写法简单,但数据量大时性能拉胯——因为数据库得跳过前面所有行才能拿到目标数据。对应的SQL你已经给出了:
SELECT * FROM products WHERE title like '%search_term%' AND price > 100 AND price < 400 AND category_id=11 ORDER BY price DESC LIMIT 10 OFFSET 10
Keyset/Seek分页的核心逻辑
Keyset分页的关键是用上一页最后一条数据的排序键值,作为下一页查询的起始锚点,数据库能直接定位到这个位置,不用傻乎乎地跳过几百上千行,性能提升明显。
第一步:先确定稳定的排序规则
Keyset分页依赖唯一的排序逻辑,不然会出现重复或遗漏数据的问题。从你给的查询结果示例来看,price是可能重复的(比如有两条price=333的记录),所以必须把唯一键id加进排序规则里,确保每一行的排序位置绝对唯一。最终我们用:price DESC, id ASC。
第二步:先查第一页,拿到锚点数据
要查第二页,得先知道第一页最后一条数据的price和id值。先执行第一页的查询:
SELECT * FROM products WHERE title like '%search_term%' AND price > 100 AND price < 400 AND category_id=11 -- 如果要按pieces筛选(比如库存大于0),直接加:AND pieces > 0 ORDER BY price DESC, id ASC LIMIT 10
假设第一页最后一条数据是id=11, price=200(对应你给的示例里的最后一条),这两个值就是我们的锚点。
第三步:用锚点查询第二页数据
把第一页最后一条的price和id作为条件,构建第二页的SQL:
SELECT * FROM products WHERE title like '%search_term%' AND price > 100 AND price < 400 AND category_id=11 -- 按需添加pieces筛选:AND pieces > 0 -- 核心的Seek条件,确保拿到的是第一页之后的数据 AND (price < 200 OR (price = 200 AND id > 11)) ORDER BY price DESC, id ASC LIMIT 10
这里的Seek条件逻辑很清晰:
- 因为是按
price DESC排序,所以下一页的产品价格必须小于锚点的价格; - 如果遇到和锚点价格相同的产品(比如还有price=200的),那就用
id来区分,只取id比锚点大的,这样就能保证不会重复拿到第一页的最后一条,也不会漏掉同价格的其他产品。
关于pieces筛选的补充
你提到要通过pieces筛选,假设pieces是库存字段,只需要在WHERE子句里加对应的条件就行,比如AND pieces > 0(筛选有库存的产品),这个条件和其他筛选条件并列,完全不影响Keyset分页的核心逻辑。
为啥Keyset分页比Offset好?
- 性能碾压:Offset分页在页数多的时候(比如第1000页),数据库要扫描并跳过前面10000条数据,慢得离谱;Keyset分页直接用锚点定位,扫描的数据量极少。
- 数据更一致:如果分页过程中有产品新增或删除,Offset分页可能会出现重复或漏数据的情况,而Keyset分页基于实际的排序键值,能完美避开这个坑。
内容的提问来源于stack exchange,提问作者tewumat
相关产品推荐
相关产品推荐

