分页查询是后台开发中最常见的功能之一,尤其当数据量大时,合理的分页策略与缓存机制不仅能减轻数据库压力,也能显著提升接口性能。
本文将从基础分页语法讲起,逐步深入到缓存优化、游标分页、总数优化等实战技巧,并提供 Java / Python / Vue 示例实现。
一、常见分页类型对比
类型 | 特点 | 适用场景 |
---|---|---|
OFFSET分页 | 支持任意页跳转,但越往后越慢 | 通用分页,如列表 |
游标分页 | 使用ID等游标字段,性能好但不支持跳页 | 数据流、feed流等 |
二、数据库分页基础语法
SELECT * FROM article ORDER BY created_at DESC LIMIT 10 OFFSET 20;
等价于第3页,每页10条。
推荐添加索引:
CREATE INDEX idx_created_at ON article(created_at);
三、Java 后端分页(Spring Boot + MyBatis Plus)
@GetMapping("/article/page")
public R page(@RequestParam int page, @RequestParam int size) {
Page<Article> pageInfo = new Page<>(page, size);
Page<Article> result = articleMapper.selectPage(pageInfo, new QueryWrapper<>());
return R.ok().put("list", result.getRecords()).put("total", result.getTotal());
}
四、Python 后端分页(Flask + SQLAlchemy)
@app.route("/article/page")
def page():
page = int(request.args.get("page", 1))
size = int(request.args.get("size", 10))
rows = Article.query.order_by(Article.created_at.desc())\
.offset((page - 1) * size).limit(size).all()
total = Article.query.count()
return jsonify({"list": [r.to_dict() for r in rows], "total": total})
五、Vue 前端分页展示(Element Plus)
<template>
<el-table :data="tableData" />
<el-pagination
v-model:current-page="page"
:page-size="size"
:total="total"
@current-change="fetchData" />
</template>
<script setup>
import { ref, onMounted } from 'vue'
import axios from 'axios'
const page = ref(1), size = ref(10), total = ref(0), tableData = ref([])
const fetchData = async () => {
const res = await axios.get('/article/page', { params: { page: page.value, size: size.value } })
tableData.value = res.data.list
total.value = res.data.total
}
onMounted(fetchData)
</script>
六、分页性能优化建议
优化方向 | 做法 |
---|---|
减少 COUNT(*) | 非必要时不查总数,或用缓存维护 |
游标分页 | 通过 WHERE id < ? 等方式实现连续读取 |
缓存热点分页 | 首页/分类页等内容通过 Redis 缓存 |
接口缓存 | GET 页码数据作为缓存键,如:page:product:list:1 |
静态分页 | 对不变内容(如公告)预生成静态页 |
七、Redis 分页缓存示例
Java 使用 Cacheable 缓存第一页:
@Cacheable(value = "article_page", key = "#page + '-' + #size")
public Page<Article> getPage(int page, int size) {
return articleMapper.selectPage(new Page<>(page, size), null);
}
Python 使用 Redis 缓存:
key = f"article:page:{page}:{size}"
cached = redis.get(key)
if cached:
return cached
# 否则查询 + 设置缓存
八、接口文档模板
分页获取文章列表
GET /article/page?page=1&size=10
Response:
{
"list": [...],
"total": 305
}
九、总结
层级 | 关键点 |
---|---|
数据库 | 建索引、控制 COUNT |
后端 | 分页库使用、游标分页、缓存结合 |
前端 | 分页组件联动、加载状态处理 |
分页作为高频功能点,推荐使用通用分页组件、缓存策略与性能监控手段相结合,避免大表拉全量、接口抖动问题,让你的系统既稳又快。