API 分页设计与实现探讨
程序员私房菜
共 4177字,需浏览 9分钟
·
2021-01-21 20:46
对于设计和实现 API 来说,当结果集包含成千上万条记录时,返回一个查询的所有结果可能是一个挑战,它给服务器、客户端和网络带来了不必要的压力,于是就有了分页的功能。
GET /api/products?page=10
{"items": [...100 products]}
如果要继续访问后续数据,则修改分页参数即可。
GET /api/products?page=11
{"items": [...another 100 products]}
在使用 offset 的情况下,通常使用 ?offset=1000 和 ?offset=1100 这种大家都熟悉的方法。它要么直接调用 OFFSET 1000 LIMIT 100 的 SQL 查询数据库,要么使用 LIMIT 乘以 page 作为查询参数。无论如何,这是一个次优的解决方案,因为无论哪种数据库都要跳过前面 offset 指定的 1000 行。而跳过额外的offset,不管是 PostgreSQL,ElasticSearch还是 MongoDB 都存在额外开销,数据库需要对它们进行排序,计数,然后将前面不用的数据扔掉。粉丝福利:手撸了 50 个 Java 项目实战后,我超神了!
举个例子。
GET /api/products
{"items": [...100 products],
"cursor": "qWe"}
API 返回一个无业务意义的字符串(游标),你可以用它来检索下一个页面。
GET /api/products?cursor=qWe
{"items": [...100 products],
"cursor": "qWr"}
=# explain analyze select id from product offset 10000 limit 100;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------
Limit (cost=1114.26..1125.40 rows=100 width=4) (actual time=39.431..39.561 rows=100 loops=1)
-> Seq Scan on product (cost=0.00..1274406.22 rows=11437243 width=4) (actual time=0.015..39.123 rows=10100 loops=1)
Planning Time: 0.117 ms
Execution Time: 39.589 ms
再看看 where (cursor) 语句如何工作:
=# explain analyze select id from product where id > 10000 limit 100;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------
Limit (cost=0.00..11.40 rows=100 width=4) (actual time=0.016..0.067 rows=100 loops=1)
-> Seq Scan on product (cost=0.00..1302999.32 rows=11429082 width=4) (actual time=0.015..0.052 rows=100 loops=1)
Filter: (id > 10000)
Planning Time: 0.164 ms
Execution Time: 0.094 ms
When using LIMIT, it is important to use an ORDER BY clause that constrains the result rows into a unique order. Otherwise you will get an unpredictable subset of the query's rows. You might be asking for the tenth through twentieth rows, but tenth through twentieth in what ordering?
explain analyze select id from product where id > 10000 limit 100
END
关注武哥聊编程
每天进步一点点
点赞是最大的支持
评论