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 开销。
  • 优化方向

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

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

相关推荐
XMYX-06 分钟前
Linux 环境下安装 MySQL 8.0.34 二进制 详细教程 附docker+k8s启动
linux·mysql·adb
叫我阿龙啊25 分钟前
sysbench对linux服务器上mysql8.0版本性能压测
linux·mysql
悟能不能悟3 小时前
now能减少mysql的压力吗
数据库·mysql
烟沙九洲7 小时前
数据库事务 ACID
数据库·mysql
卜锦元9 小时前
华为高斯Gauss数据库版本与兼容协议--详解(附带Gorm连接示例代码)
数据库·mysql·华为·postgresql
霍格沃兹软件测试开发10 小时前
Playwright 自动化测试系列(6)| 第三阶段:测试框架集成指南:参数化测试 + 多浏览器并行执行
java·数据库·mysql·自动化
黄昏恋慕黎明10 小时前
Mysql中的索引
数据库·mysql
神仙别闹13 小时前
基于Java+MySQL实现(Web)文件共享管理系统(仿照百度文库)
java·前端·mysql
_代号00714 小时前
MySQL梳理二:索引
后端·mysql