知识卡片

查询慢的两层诊断框架:请求了不需要的数据 / 扫描了过多记录

结构图卡

内容

诊断一个慢查询时,与其直接跳进”加索引/改SQL写法”这类具体手段,不如先按 “访问了多少数据”这条主线分两层拆解问题,再决定用哪种手段。第一层问”是否 向数据库请求了不需要的数据”:常见的三种浪费形态是——误以为数据库会像 生成器一样按需产出结果、只在客户端取用前N行就关闭结果集(实际MySQL会先 算出全部结果集,客户端拿到手才丢弃多余部分,正确做法是查询本身就带 LIMIT);多表关联时用SELECT *带出并不需要的整表列(不仅浪费I/O/内存/ CPU,还会让优化器无法使用 [[覆盖索引让查询只读索引无须回表]]这类索引覆盖优化);以及重复执行完全 相同的查询取相同数据而不做应用层缓存。第二层问”MySQL执行时是否扫描了 过多记录”:衡量这一层用响应时间、扫描行数、返回行数三个指标交叉判断, 其中”扫描行数:返回行数”的比值最直观——理想情况接近1:1,比值越大说明 访问路径效率越低;而访问路径的效率本质上取决于EXPLAIN的type列反映的 访问类型(全表扫描→索引扫描→范围扫描→唯一值查询,一路对应扫描行数从多 到少)。这个两层框架的价值在于给出了一条排查顺序:先确认”要的数据本身是 不是就该更少”(改写查询/加LIMIT/去掉多余列),再确认”拿到这些数据的路径 是不是够短”(补合适的索引),而不是一上来就在两者之间反复试探。

结构图

flowchart TD
    A[查询响应慢] --> B{第一层:<br/>是否请求了不需要的数据?}
    B -->|结果集未加LIMIT就在客户端丢弃| C[加LIMIT/改写查询范围]
    B -->|SELECT *带出多余列| D[只选需要的列]
    B -->|重复查同样的数据| E[应用层加缓存]
    B -->|请求本身已经精确| F{第二层:<br/>是否扫描了过多记录?}
    F --> G[看扫描行数:返回行数比值]
    F --> H[看EXPLAIN的type访问类型]
    G --> I[比值远大于1:1 → 访问路径效率低]
    H --> I
    I --> J[补合适索引缩短访问路径]

参考来源

- 位置:《高性能MySQL:第3版》第6章"查询性能优化"6.2节"慢查询基础: 优化数据访问"(6.2.1、6.2.2小节)(源文件: _epub-src/OEBPS/Text/part0013.xhtml) - 结论依据:原文明确"查询性能低下最基本的原因是访问的数据太多……在确定 查询只返回需要的数据以后,接下来应该看看查询为了返回结果是否扫描了 过多的数据……对于MySQL,最简单的衡量查询开销的三个指标如下:响应 时间、扫描的行数、返回的行数",把慢查询诊断明确拆成"请求的数据量"和 "扫描的数据量"两层,并给出各自的具体判断信号。 - 原始内容:查询性能低下最基本的原因是访问的数据太多……对于MySQL, 最简单的衡量查询开销的三个指标如下:响应时间、扫描的行数、返回的 行数。