gorm分表操作

gorm分表操作
安安gorm分页操作
一.分页概述
一、为什么要分页?
- 查询结果太多时,不可能一次性全查出来。
- 分页的作用:控制数据量(每页多少条),并能跳到指定页。
- 在 SQL 中分页主要靠
LIMIT+OFFSET(或 MySQL 8+ 的LIMIT ... OFFSET/ROW_NUMBER窗口函数)。
二、GORM 分页的常见写法
1. 基本分页
1 | type User struct { |
对应 SQL(查询第 2 页,每页 10 条):
1 | SELECT * FROM users LIMIT 10 OFFSET 10; |
2. 带排序的分页
分页查询通常要加排序,否则不同页之间可能会重复/丢失数据:
1 | db.Order("id DESC").Limit(pageSize).Offset((page - 1) * pageSize).Find(&users) |
3. 带总数统计(常用)
分页通常需要总记录数(前端显示“共 N 页”)。
1 | var total int64 |
4. 封装成函数
可以封装成通用分页函数,避免重复写逻辑:
1 | type PageResult[T any] struct { |
调用:
1 | var users []User |
5. Cursor 分页(大数据时更高效)
如果数据量非常大,OFFSET 会越来越慢(因为 MySQL 要扫描并丢弃前面的行)。
可以用 基于游标的分页,例如“取 id > 上一页最后一个 id 的数据”:
1 | var users []User |
优点:性能稳定,适合无限滚动、导出大数据等场景。
缺点:只能“向前翻页”,不能随便跳转到第 N 页。
三、注意事项
- 必须加排序,否则分页结果可能重复或缺失。
Offset的性能问题:偏移量越大越慢,适合小数据量分页。- 大数据推荐用 游标分页(Cursor Pagination)。
- 统计总数时
db.Count(&total)要在分页前执行,否则只会统计当前页数量。
✅ 总结:
- 小数据分页:
Limit + Offset + Order。 - 需要总页数:加
Count。 - 大数据高性能:游标分页(
id > lastID)。 - 封装分页函数提高复用性。
二.offset详解
1. Offset 是什么?
在 SQL 里,OFFSET n 的意思是:跳过前 n 条记录,从第 n+1 条开始返回。
搭配 LIMIT m,就是:从第 n+1 条开始,取 m 条记录。
2. 举例说明
假设 users 表里有 20 条记录(id 从 1 到 20),排序是 ORDER BY id ASC。
第一页(page=1, pageSize=5):
1
SELECT * FROM users ORDER BY id ASC LIMIT 5 OFFSET 0;
👉 跳过 0 条,从第 1 条开始取 5 条 → 返回 id = 1..5
第二页(page=2, pageSize=5):
1
SELECT * FROM users ORDER BY id ASC LIMIT 5 OFFSET 5;
👉 跳过前 5 条,从第 6 条开始取 5 条 → 返回 id = 6..10
第三页(page=3, pageSize=5):
1
SELECT * FROM users ORDER BY id ASC LIMIT 5 OFFSET 10;
👉 跳过前 10 条,从第 11 条开始取 5 条 → 返回 id = 11..15
所以 (page - 1) * pageSize 这个计算公式就是:需要跳过多少条,才能到这一页的起始位置。
3. 为什么分页必须加 Order?
因为如果不加 ORDER BY,数据库返回行的顺序是不确定的。
那分页可能出现:第一页查到 id=1..5,第二页可能又包含 id=3..7,结果重复或丢数据。
所以分页时一般写成:
1 | db.Order("id ASC").Limit(pageSize).Offset((page-1)*pageSize).Find(&users) |
4. Offset 的性能问题
OFFSET n实际上是数据库先扫描前 n 条再丢弃,然后返回后面的。- 当数据量很大(比如 page=100000),就要扫描很多行 → 查询变慢。
- 解决办法:用 游标分页(cursor pagination),比如
WHERE id > lastID。
✅ 总结一句:
Offset 就是“跳过多少条记录”。 在分页公式 (page-1)*pageSize 里,它确保你能跳过前面的页数,直接定位到第 N 页的第一条数据。
三.page和pageSize详解
1. page
- 表示第几页
- 通常从 1 开始(有些程序员喜欢从 0 开始,但主流是 1)。
- 举例:
page=1→ 第一页page=2→ 第二页page=3→ 第三页
2. pageSize
- 表示每一页要显示多少条记录
- 就是分页的“容量”。
- 举例:
pageSize=10→ 每页 10 条pageSize=20→ 每页 20 条
3. 结合 page 和 pageSize 的效果
分页公式:
1 | OFFSET = (page - 1) * pageSize |
假设有 users 表,id = 1..20,总共有 20 条数据:
| page | pageSize | SQL 查询 | 结果 (id) |
|---|---|---|---|
| 1 | 5 | LIMIT 5 OFFSET 0 |
1..5 |
| 2 | 5 | LIMIT 5 OFFSET 5 |
6..10 |
| 3 | 5 | LIMIT 5 OFFSET 10 |
11..15 |
| 4 | 5 | LIMIT 5 OFFSET 15 |
16..20 |
| 2 | 10 | LIMIT 10 OFFSET 10 |
11..20 |
| 3 | 7 | LIMIT 7 OFFSET 14 |
15..20(6 条) |
4. 直观理解
page👉 你在翻第几页pageSize👉 每页能装多少条数据OFFSET👉 跳过多少条,才能到这一页的起点
所以:
- page 控制“翻到哪一页”
- pageSize 控制“每页多少条”

