例如:SELECT id FROM table WHERE condition LIMIT offset, N。
主查询阶段:
通过主键索引或内连接(INNER JOIN)回表获取完整数据,仅扫描 N 行。
例如:SELECT * FROM table INNER JOIN (子查询) ON id。
3. 执行流程对比
步骤
传统分页
延迟关联
筛选主键
全表扫描或二级索引扫描,需回表获取所有数据
仅通过覆盖索引扫描,无需回表
数据获取
直接返回扫描到的数据
根据子查询的主键 ID 回表获取数据
扫描行数
offset + N
N(仅目标数据)
适用场景
浅分页(offset 小)
深度分页(offset 大)或数据量大的场景
二、延迟关联的实现方式
1. 基于 INNER JOIN 的实现
SELECT t1.*
FROM main_table t1
INNER JOIN (
SELECT id
FROM main_table
WHERE create_time > '2023-01-01'
ORDER BY create_time
LIMIT 100000, 10
) AS t2
ON t1.id = t2.id;
优化点:
子查询通过覆盖索引(如 (create_time, id))快速定位主键。
主查询通过主键索引高效回表,仅扫描 10 行。
2. 基于子查询的实现
SELECT *
FROM main_table
WHERE id IN (
SELECT id
FROM main_table
WHERE create_time > '2023-01-01'
ORDER BY create_time
LIMIT 100000, 10
);
适用性: 部分数据库(如 MySQL)可能对子查询优化不足,INNER JOIN 更高效。
三、延迟关联的适用场景
1. 深度分页查询
场景:用户需要访问第 1000 页数据(每页 10 条),即 LIMIT 10000, 10。
优化效果:扫描行数从 10010 行减少到 10 行。
2. 覆盖索引可用
前提:需创建覆盖索引(如 (create_time, id)),否则无法跳过回表。
3. 高并发查询
优势:减少锁竞争和 I/O 压力,提升吞吐量。
4. 复杂条件过滤
案例:筛选出满足条件的用户 ID,再关联其他表获取详细信息。
四、延迟关联的优势与限制
1. 优势
优势
说明
减少回表
子查询阶段仅访问索引,无需回表获取完整数据。
避免全表扫描
通过覆盖索引快速定位目标行,减少无效扫描。
降低 CPU 开销
减少排序和过滤的数据量。
灵活适配业务
支持复杂条件的分页优化。
2. 限制
限制
说明
依赖覆盖索引
若无合适索引,优化效果受限。
不适用随机排序
若排序字段与索引无关,需全表扫描。
主键需有序
若主键非自增或存在删除操作,可能导致分页遗漏。
子查询性能差异
不同数据库对子查询的优化能力不同。
五、延迟关联的最佳实践
1. 索引设计
创建覆盖索引:例如 (create_time, id),覆盖查询条件和排序字段。
避免宽索引:仅包含必要字段,减少索引大小。
2. SQL 改写
优先用 INNER JOIN:比子查询更高效。
分页游标替代 LIMIT:如 WHERE id > last_id LIMIT 10,避免偏移量问题。