SQL执行计划分析-分页查询

一、SQL 执行计划分析

以下是当前 SQL 的执行计划分析:

plaintext 复制代码
+----+-------------+-------------------------------+------------+------+-------------------------------------------------------------+-------------------------------+---------+-------------+---------+----------+-------------+
| id | select_type | table                         | partitions | type | possible_keys                                               | key                           | key_len | ref         | rows    | filtered | Extra       |
+----+-------------+-------------------------------+------------+------+-------------------------------------------------------------+-------------------------------+---------+-------------+---------+----------+-------------+
|  1 | SIMPLE      | ecif_point_subjects_info_2023 | p202312    | ref  | ecif_point_subjects_info_idx2,ecif_point_subjects_info_idx3 | ecif_point_subjects_info_idx2 | 212     | const,const | 1378916 |   100.00 | Using index |
+----+-------------+-------------------------------+------------+------+-------------------------------------------------------------+-------------------------------+---------+-------------+---------+----------+-------------+
plaintext 复制代码
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| EXPLAIN                                                                                                                                                                                                                                                                                                                                                                                                           |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| -> Limit/Offset: 5/300 row(s)  (cost=342931.18 rows=5)
    -> Group aggregate: count(1), sum(ecif_point_subjects_info_2023.debt_total_amt), sum(ecif_point_subjects_info_2023.crdt_total_amt)  (cost=342931.18 rows=1378916)
        -> Covering index lookup on ecif_point_subjects_info_2023 using ecif_point_subjects_info_idx2 (batch_date='2023-12-30', batch_id='20231230803')  (cost=205039.58 rows=1378916)
 |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

二、执行计划字段详解

1. 基础执行计划字段

  • id :查询的唯一标识符。1 表示这是第一个查询(没有子查询或联合查询)。
  • select_type :查询类型。SIMPLE 表示这是一个简单的查询,不包含子查询或联合查询。
  • table :查询涉及的表名。ecif_point_subjects_info_2023
  • partitions :查询涉及的分区。p202312 表示查询只涉及 2023-12 的数据分区。
  • type :连接类型。ref 表示 MySQL 使用了非唯一索引进行查找。
  • possible_keys :MySQL 可能使用的索引。这里有 ecif_point_subjects_info_idx2ecif_point_subjects_info_idx3
  • key :MySQL 实际使用的索引。ecif_point_subjects_info_idx2 是实际使用的索引。
  • key_len :使用的索引长度。212 字节,这表明索引包含了多个字段(batch_date, batch_id, br_no, tx_br_no, debt_total_amt, crdt_total_amt)。
  • ref :显示索引的哪一列被使用。const,const 表示 batch_datebatch_id 被用作常量值进行查询。
  • rows :MySQL 估计需要扫描的行数。1378916 表示 MySQL 估计需要扫描大约 138 万行数据。
  • filtered :表示查询条件过滤后的行数比例。100.00 表示没有进一步的过滤。
  • Extra :额外的信息。Using index 表示 MySQL 使用了覆盖索引,不需要回表查询。

2. 树状执行计划分析

  • Limit/Offset: 5/300:表示查询结果将被限制为从第 300 行开始,返回 5 行数据。
  • Group aggregate :表示 MySQL 正在执行 GROUP BY 聚合操作,计算 COUNT(1)SUM(debt_total_amt)SUM(crdt_total_amt)
  • Covering index lookup :表示 MySQL 使用了覆盖索引 ecif_point_subjects_info_idx2,直接从索引中获取数据,不需要回表查询。

三、性能分析

1. 索引使用分析

  • 当前查询使用了索引 ecif_point_subjects_info_idx2,该索引包含字段:

    sql 复制代码
    (batch_date, batch_id, br_no, tx_br_no, debt_total_amt, crdt_total_amt)
  • 查询条件 batch_date = '2023-12-30' AND batch_id = '20231230803' 完全匹配索引前缀,因此 MySQL 能够高效地定位数据。

  • GROUP BY br_no, tx_br_no 也匹配索引的前缀字段,因此可以利用索引进行排序,避免额外的排序操作。

2. 扫描行数分析

  • 预计需要扫描 138 万行数据,这主要是因为:
    • GROUP BY 操作需要遍历所有符合条件的数据,进行聚合计算。
    • LIMIT 300, 5 导致 MySQL 需要扫描前 300 行数据,然后丢弃这些数据,只返回最后 5 行。

3. 性能瓶颈

  • 扫描行数大:虽然使用了覆盖索引,但扫描 138 万行数据仍然会带来较大的 I/O 和 CPU 开销。
  • 深分页问题LIMIT 300, 5 是典型的深分页场景,MySQL 需要扫描前 300 行数据并丢弃,效率较低。
  • 聚合操作开销GROUP BY 操作需要对大量数据进行分组和统计,增加了 CPU 消耗。

四、优化建议

1. 优化索引

  • 确保索引字段匹配查询条件和排序字段
    • 当前索引 ecif_point_subjects_info_idx2 已经覆盖了 batch_date, batch_id, br_no, tx_br_no, debt_total_amt, crdt_total_amt,能够支持当前查询。
    • 如果查询中还涉及其他字段(如 dept_no, field2, bal_ind),可以考虑扩展索引字段。

2. 减少扫描行数

  • 缩小查询范围 :如果业务允许,可以进一步缩小查询范围,例如增加 br_notx_br_no 的过滤条件。
  • 使用更细粒度的分区 :如果数据按 br_notx_br_no 分布不均,可以考虑按这些字段进行子分区,以减少扫描的数据量。

3. 优化分页

  • 避免深分页
    • 使用游标分页(Cursor-based Pagination)代替 LIMIT offset, size,例如:

      sql 复制代码
      SELECT batch_id, COUNT(1) AS countAll, ...
      FROM ecif_point_subjects_info_2023
      WHERE batch_date = '2023-12-30' AND batch_id = '20231230803'
        AND (br_no, tx_br_no) > ('last_br_no', 'last_tx_br_no')
      GROUP BY br_no, tx_br_no
      ORDER BY br_no, tx_br_no
      LIMIT 5;
    • 每次查询使用上一次查询的最后一条记录的 br_notx_br_no 作为游标。

4. 缓存结果

  • 对于频繁查询的聚合结果,可以使用缓存(如 Redis)来减少数据库的负载。

5. 批量计算

  • 如果聚合结果用于报表展示,可以考虑在后台异步计算并存储结果,减少实时查询的压力。

五、总结

  • 当前查询性能瓶颈

    • 扫描行数大(约 138 万行)。
    • 深分页导致不必要的数据扫描。
    • 聚合操作增加 CPU 开销。
  • 优化方向

    • 优化索引,确保字段匹配。
    • 使用游标分页减少深分页带来的性能问题。
    • 缩小查询范围,减少扫描行数。
    • 使用缓存或异步计算减少实时查询压力。

通过以上优化措施,可以显著提升查询性能,尤其是在大数据量和高并发场景下。

相关推荐
于眠牧北2 天前
MySQL的锁类型,表锁,行锁,MVCC中所使用的临键锁
mysql
Turnip12024 天前
深度解析:为什么简单的数据库"写操作"会在 MySQL 中卡住?
后端·mysql
加号35 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
シ風箏5 天前
MySQL【部署 04】Docker部署 MySQL8.0.32 版本(网盘镜像及启动命令分享)
数据库·mysql·docker
WeiXin_DZbishe5 天前
基于django在线音乐数据采集的设计与实现-计算机毕设 附源码 22647
javascript·spring boot·mysql·django·node.js·php·html5
爱可生开源社区5 天前
MySQL 性能优化:真正重要的变量
数据库·mysql
小马爱打代码5 天前
MySQL性能优化核心:InnoDB Buffer Pool 详解
数据库·mysql·性能优化
风流 少年5 天前
mysql mcp
数据库·mysql·adb
西门吹雪分身5 天前
mysql之数据离线迁移
数据库·mysql
轩情吖5 天前
MySQL初识
android·数据库·sql·mysql·adb·存储引擎