手把手教你用scDrug分析肝癌单细胞数据:从Scanpy预处理到药物预测的完整实战
2026/5/31 18:13:37
“MySQL 扫描 1,000,010 行 → 磁盘 I/O 爆炸”是深度分页查询的典型性能灾难。其本质是全表扫描 + 随机 I/O + 内存不足的三重叠加效应。
LIMIT offset, size的执行逻辑SELECT*FROMordersORDERBYidLIMIT1000000,10;id排序(若无索引则 filesort)💡核心认知:
MySQL 无法“跳过”中间行,必须物理扫描所有前置行
| 场景 | 扫描方式 | I/O 类型 |
|---|---|---|
| 无索引 | 全表扫描 + filesort | 随机 I/O(HDD ≈ 10ms/行) |
| 有主键索引 | 索引扫描 | 顺序 I/O(HDD ≈ 0.1ms/行) |
📌关键点:
即使有索引,仍需扫描 1,000,010 行(仅避免排序开销)
| 指标 | HDD | SSD |
|---|---|---|
| 随机读 I/O 延迟 | 8–12ms | 0.05–0.1ms |
| 1,000,010 行总耗时 | 2.78 小时 | 1.67 分钟 |
⚠️现实:
即使使用 SSD,100 万行扫描仍需分钟级响应
sort_buffer_size)溢出 → 创建磁盘临时文件ORDER BY)消耗大量 CPU 周期-- 记录上一页最后 id=1000000SELECT*FROMordersWHEREid>1000000ORDERBYidLIMIT10;| 指标 | OFFSET 方案 | 游标方案 |
|---|---|---|
| 扫描行数 | 1,000,010 | 10 |
| HDD 耗时 | 2.78 小时 | 0.1ms |
| SSD 耗时 | 1.67 分钟 | 0.001ms |
?cursor=1000000)SELECT*FROMlogsWHERE(created_at,id)>('2023-01-01',1000)ORDERBYcreated_at,idLIMIT10;| 陷阱 | 破局方案 |
|---|---|
| 忽略排序字段唯一性 | 复合排序末尾加主键确保连续 |
| 未使用覆盖索引 | 确保WHERE+ORDER BY字段有联合索引 |
| 盲目使用 OFFSET | 深度分页必用游标方案 |
**“扫描不是查询,
而是性能的悬崖——
- 当你使用 OFFSET,
你在支付线性成本;- 当你切换游标,
你在享受常数时间;- 当你利用索引,
你在消除随机 I/O。真正的查询优化,
始于对执行计划的敬畏,
成于对细节的精控。”
从今天起:
WHERE id > last_id)EXPLAIN验证执行计划(type=range)long_query_time=1)因为最好的分页,
不是跳过百万行,
而是精准定位下一程。