Mysql

关注公众号 jb51net

关闭
首页 > 数据库 > Mysql > MySQL深度分页问题

MySQL深度分页问题的三种解决方法

作者:Dolphin_Home

在 MySQL 中解决深度分页问题的核心思路是减少扫描的数据量,尤其是避免通过 LIMIT offset, size 导致的大范围数据扫描,以下是三种优化方法及其原理、适用场景和注意事项,需要的朋友可以参考下

前言

在 MySQL 中解决深度分页问题的核心思路是减少扫描的数据量,尤其是避免通过 LIMIT offset, size 导致的大范围数据扫描。以下是三种优化方法及其原理、适用场景和注意事项:

1. 子查询 + 覆盖索引(延迟关联)

原理

示例 SQL

SELECT * FROM mianshiya 
WHERE name = 'yupi' AND id >= (
    SELECT id FROM mianshiya 
    WHERE name = 'yupi' 
    ORDER BY id LIMIT 99999990, 1
)
ORDER BY id LIMIT 10;

或使用 JOIN 优化:

SELECT * FROM mianshiya 
INNER JOIN (
    SELECT id FROM mianshiya 
    WHERE name = 'yupi' 
    ORDER BY id LIMIT 99999990, 10
) AS tmp ON mianshiya.id = tmp.id;

关键点

2. 记录最大 ID(游标分页)

原理

适用场景

示例 SQL

-- 第一页
SELECT * FROM mianshiya WHERE name = 'yupi' ORDER BY id LIMIT 10;
-- 后续页(假设上一页最大 id 为 100)
SELECT * FROM mianshiya WHERE name = 'yupi' AND id > 100 ORDER BY id LIMIT 10;

注意事项

3. Elasticsearch 优化

原理

ES 分页示例

{
  "query": { "match": { "name": "yupi" } },
  "sort": [{ "id": "asc" }],
  "size": 10,
  "search_after": [100]  -- 上一页最后一条记录的排序值
}

ES 注意事项

其他优化思路

总结

方法优点缺点适用场景
子查询 + 覆盖索引支持跳页,通用性强依赖联合索引设计需频繁分页且允许跳页
记录最大 ID性能最优,复杂度低仅支持连续分页连续分页(如瀑布流)
Elasticsearch适合复杂搜索,分布式性能好维护成本高,ES 需额外学习高并发搜索+分页场景

核心要点

扩展:MySQL中 join、inner join、left join、right join区别

在 MySQL 中,JOIN 操作用于将多个表中的数据关联起来。以下是 INNER JOINLEFT JOINRIGHT JOIN 的核心区别和用法总结,帮助你快速分清它们:

1. INNER JOIN(内连接)

SELECT * 
FROM 表A
INNER JOIN 表B ON 表A.键 = 表B.键;

2. LEFT JOIN(左外连接)

SELECT * 
FROM 表A
LEFT JOIN 表B ON 表A.键 = 表B.键;

3. RIGHT JOIN(右外连接)

SELECT * 
FROM 表A
RIGHT JOIN 表B ON 表A.键 = 表B.键;

4. JOIN(默认是 INNER JOIN)

说明:在 MySQL 中,直接写 JOIN 等价于 INNER JOIN

SELECT * 
FROM 表A
JOIN 表B ON 表A.键 = 表B.键; -- 等同于 INNER JOIN

对比总结

类型行为适用场景
INNER JOIN仅返回两个表匹配的行需要精确匹配的数据(如订单和商品)
LEFT JOIN返回左表全部数据 + 右表匹配的数据(右表无匹配则为 NULL保留左表全部数据(如所有员工信息)
RIGHT JOIN返回右表全部数据 + 左表匹配的数据(左表无匹配则为 NULL保留右表全部数据(如所有部门信息)

关键注意事项

  1. 方向性LEFT JOIN 和 RIGHT JOIN 的方向取决于表的书写顺序。
    • LEFT JOIN 以左表为主,RIGHT JOIN 以右表为主。
  2. 过滤条件
    • 在 LEFT JOIN 中,若在 WHERE 子句中对右表字段过滤(如 WHERE 表B.键 IS NULL),会筛选出仅存在于左表但右表无匹配的行。
  3. 性能
    • INNER JOIN 通常效率更高,因为它涉及的数据量更小。
    • LEFT/RIGHT JOIN 可能因处理 NULL 值而略慢,尤其是在大表中。

示例演示

数据准备
-- 员工表(employees)
+-------------+-------+---------------+
| employee_id | name  | department_id |
+-------------+-------+---------------+
| 1           | 张三  | 101           |
| 2           | 李四  | 102           |
| 3           | 王五  | NULL          |
+-------------+-------+---------------+

-- 部门表(departments)
+---------------+-----------------+
| department_id | department_name |
+---------------+-----------------+
| 101           | 技术部          |
| 102           | 市场部          |
| 103           | 财务部          |
+---------------+-----------------+

查询结果对比

INNER JOIN(匹配数据):

SELECT * 
FROM employees
INNER JOIN departments 
  ON employees.department_id = departments.department_id;

结果

| 1 | 张三 | 101 | 101 | 技术部 |
| 2 | 李四 | 102 | 102 | 市场部 |

LEFT JOIN(保留所有员工):

SELECT * 
FROM employees
LEFT JOIN departments 
  ON employees.department_id = departments.department_id;

结果

| 1 | 张三 | 101 | 101 | 技术部 |
| 2 | 李四 | 102 | 102 | 市场部 |
| 3 | 王五 | NULL| NULL| NULL   | -- 员工无部门,右表字段为 NULL

RIGHT JOIN(保留所有部门):

SELECT * 
FROM employees
RIGHT JOIN departments 
  ON employees.department_id = departments.department_id;

结果

| 1 | 张三 | 101 | 101 | 技术部 |
| 2 | 李四 | 102 | 102 | 市场部 |
| NULL| NULL| NULL| 103 | 财务部 | -- 部门无员工,左表字段为 NULL

总结

以上就是MySQL深度分页问题的三种解决方法的详细内容,更多关于MySQL深度分页问题的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文