ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

SELECT * FROM orders WHERE id > 1000000 ORDER BY id LIMIT 10;的庖丁解牛

SELECT * FROM orders WHERE id > 1000000 ORDER BY id LIMIT 10;的庖丁解牛

SELECT * FROM orders WHERE id > 1000000 ORDER BY id LIMIT 10;是高性能分页查询的典范,它通过游标分页(Cursor-based Pagination)避免了传统OFFSET的性能陷阱。


一、执行机制:为什么高效?

▶ 1.执行计划解析
EXPLAINSELECT*FROMordersWHEREid>1000000ORDERBYidLIMIT10;
  • 关键输出:
    type: range key: PRIMARY rows: 10 Extra: Using where; Using index
▶ 2.执行流程

定位 id=1000000

通过聚簇索引向右扫描

读取下 10 行

返回结果

  • 核心优势:
    • 仅扫描 10 行(而非OFFSET的 1,000,010 行)
    • 直接利用聚簇索引(InnoDB 主键即数据存储顺序)

💡核心认知:
WHERE id > N+ORDER BY id= 直接跳转到 N+1 位置


二、索引利用:聚簇索引的威力

▶ 1.InnoDB 聚簇索引结构
  • 数据存储:
    • 主键索引的叶子节点 = 完整行数据
    • 物理存储按主键顺序排列
  • 查询优势:
    • WHERE id > N→ 直接定位到 B+ 树的 N+1 位置
    • 顺序读取后续 10 行 →无随机 I/O
▶ 2.对比非聚簇索引
  • MyISAM 表:
    • 主键索引 ≠ 数据存储顺序
    • 需额外回表 → 性能下降
  • InnoDB 非主键查询:
    • 若id非主键 → 需回表 → 性能下降

📌关键点:
此查询高效的前提是id为 InnoDB 聚簇索引(通常是自增主键)


三、工程价值:游标分页的实践

▶ 1.前端交互设计
  • 传递游标:
    • 前端保存上一页最后一条的id
    • 下一页请求携带cursor=id
  • 示例 API:
    GET /orders?cursor=1000000&limit=10
▶ 2.后端实现
// Laravel 示例publicfunctionindex(Request$request){$cursor=$request->input('cursor',0);$limit=min($request->input('limit',10),100);$orders=Order::where('id','>',$cursor)->orderBy('id')->limit($limit)->get();returnresponse()->json(['data'=>$orders,'next_cursor'=>$orders->last()?->id]);}
▶ 3.性能对比
查询方式扫描行数响应时间(1亿行表)
LIMIT 1000000, 101,000,01012.3 秒
游标分页100.008 秒

四、避坑指南

陷阱破局方案
id 非自增主键确保排序字段是聚簇索引
并发插入导致漏数据接受最终一致性(业务可容忍)
反向分页困难单独实现WHERE id < cursor ORDER BY id DESC

五、终极心法

**“游标不是技巧,
而是索引的舞蹈——

  • 当你利用聚簇,
    你在消除随机;
  • 当你传递锚点,
    你在跳过扫描;
  • 当你接受最终一致,
    你在拥抱现实。

真正的分页优化,
始于对存储的敬畏,
成于对细节的精控。”


结语

从今天起:

  1. 深度分页必用游标方案
  2. 确保排序字段是聚簇索引
  3. 用EXPLAIN验证执行计划(type=range)

因为最好的分页,
不是跳过百万行,
而是精准定位下一程。

返回列表