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

sql表结构和执行计划

mysql 复制代码
-- --------------------------------------------------------------------------
-- table structure
-- --------------------------------------------------------------------------
| ecif_point_subjects_info_2023 | CREATE TABLE `ecif_point_subjects_info_2023` (
  `id` varchar(32) NOT NULL COMMENT '主键ID',
  `batch_id` varchar(32) NOT NULL COMMENT '批量id',
  `batch_date` varchar(20) NOT NULL COMMENT '批量日期',
  `br_no` varchar(128) NOT NULL COMMENT '法人机构',
  `tx_br_no` varchar(32) NOT NULL COMMENT '交易机构',
  `dept_no` varchar(32) DEFAULT NULL COMMENT '条线(部门)',
  `subject_no` varchar(32) NOT NULL COMMENT '科目编号',
  `subject_name` varchar(64) DEFAULT NULL COMMENT '科目名称',
  `bal_ind` varchar(8) DEFAULT NULL COMMENT '余额方向1 借 2 贷 0 双向',
  `debt_total_amt` decimal(16,2) DEFAULT NULL COMMENT '借发生额',
  `crdt_total_amt` decimal(16,2) DEFAULT NULL COMMENT '贷发生额',
  `adjust_flag` varchar(4) NOT NULL DEFAULT 'N' COMMENT '手工调账科目标识 Y  是手工调账 N  不是手工调账科目 默认N',
  `create_time` varchar(20) DEFAULT NULL COMMENT '创建时间',
  `modify_time` varchar(20) DEFAULT NULL COMMENT '结束时间',
  `field1` varchar(128) DEFAULT NULL COMMENT '扩展1',
  `field2` varchar(128) DEFAULT NULL COMMENT '扩展2',
  PRIMARY KEY (`id`,`batch_date`) USING BTREE,
  KEY `ecif_point_subjects_info_idx2` (`batch_date`,`batch_id`,`br_no`,`tx_br_no`,`debt_total_amt`,`crdt_total_amt`),
  KEY `ecif_point_subjects_info_idx3` (`batch_date`,`batch_id`,`br_no`,`tx_br_no`,`dept_no`,`field2`,`bal_ind`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='积分供数科目表min'
/*!50500 PARTITION BY RANGE  COLUMNS(batch_date)
(PARTITION p202301 VALUES LESS THAN ('2023-02-01') COMMENT = '2023年01月份数据' ENGINE = InnoDB,
 PARTITION p202302 VALUES LESS THAN ('2023-03-01') COMMENT = '2023年02月份数据' ENGINE = InnoDB,
 PARTITION p202303 VALUES LESS THAN ('2023-04-01') COMMENT = '2023年03月份数据' ENGINE = InnoDB,
 PARTITION p202304 VALUES LESS THAN ('2023-05-01') COMMENT = '2023年04月份数据' ENGINE = InnoDB,
 PARTITION p202305 VALUES LESS THAN ('2023-06-01') COMMENT = '2023年05月份数据' ENGINE = InnoDB,
 PARTITION p202306 VALUES LESS THAN ('2023-07-01') COMMENT = '2023年06月份数据' ENGINE = InnoDB,
 PARTITION p202307 VALUES LESS THAN ('2023-08-01') COMMENT = '2023年07月份数据' ENGINE = InnoDB,
 PARTITION p202308 VALUES LESS THAN ('2023-09-01') COMMENT = '2023年08月份数据' ENGINE = InnoDB,
 PARTITION p202309 VALUES LESS THAN ('2023-10-01') COMMENT = '2023年09月份数据' ENGINE = InnoDB,
 PARTITION p202310 VALUES LESS THAN ('2023-11-01') COMMENT = '2023年10月份数据' ENGINE = InnoDB,
 PARTITION p202311 VALUES LESS THAN ('2023-12-01') COMMENT = '2023年11月份数据' ENGINE = InnoDB,
 PARTITION p202312 VALUES LESS THAN ('2024-01-01') COMMENT = '2023年12月份数据' ENGINE = InnoDB) */ |

-- --------------------------------------------------------------------------
-- explain
-- --------------------------------------------------------------------------
mysql> EXPLAIN
SELECT * FROM ecif_point_subjects_info_2023 
WHERE batch_date = '2023-12-30' AND batch_id = '20231230803'
ORDER BY br_no ASC , tx_br_no ASC , dept_no ASC , field2 ASC , bal_ind ASC 
LIMIT 500000,5;
+----+-------------+-------------------------------+------------+------+-------------------------------------------------------------+-------------------------------+---------+-------------+---------+----------+-------+
| 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_idx3 | 212     | const,const | 1200102 |   100.00 | NULL  |
+----+-------------+-------------------------------+------------+------+-------------------------------------------------------------+-------------------------------+---------+-------------+---------+----------+-------+
1 row in set (0.05 sec)

mysql> EXPLAIN FORMAT=TREE
SELECT * FROM ecif_point_subjects_info_2023 
WHERE batch_date = '2023-12-30' AND batch_id = '20231230803'
ORDER BY br_no ASC , tx_br_no ASC , dept_no ASC , field2 ASC , bal_ind ASC 
LIMIT 500000,5;
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| EXPLAIN                                                                                                                                                                                                                            |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| -> Limit/Offset: 5/500000 row(s)  (cost=300076.70 rows=5)
    -> Index lookup on ecif_point_subjects_info_2023 using ecif_point_subjects_info_idx3 (batch_date='2023-12-30', batch_id='20231230803')  (cost=300076.70 rows=1200102)
 |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.04 sec)

SQL执行计划分析

1. 执行计划表头信息

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_idx3 | 212     | const,const | 1200102 |   100.00 | NULL  |
+----+-------------+-------------------------------+------------+------+-------------------------------------------------------------+-------------------------------+---------+-------------+---------+----------+-------+
各列含义分析:
  • 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_idx3 是实际使用的索引。
  • key_len :使用的索引长度。212 字节,这表明索引包含了多个字段(batch_date, batch_id, br_no, tx_br_no, dept_no, field2, bal_ind)。
  • ref :显示索引的哪一列被使用。const,const 表示 batch_datebatch_id 被用作常量值进行查询。
  • rows :MySQL 估计需要扫描的行数。1200102 表示 MySQL 估计需要扫描大约 120 万行数据。
  • filtered :表示查询条件过滤后的行数比例。100.00 表示没有进一步的过滤。
  • Extra :额外的信息。NULL 表示没有额外的操作。

2. 执行计划的树状结构分析

plaintext 复制代码
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| EXPLAIN                                                                                                                                                                                                                            |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| -> Limit/Offset: 5/500000 row(s)  (cost=300076.70 rows=5)
    -> Index lookup on ecif_point_subjects_info_2023 using ecif_point_subjects_info_idx3 (batch_date='2023-12-30', batch_id='20231230803')  (cost=300076.70 rows=1200102)
 |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
各部分含义分析:
  • Limit/Offset :表示查询结果将被限制为从第 500,000 行开始,返回 5 行数据。cost=300076.70 表示执行该操作的成本,rows=5 表示最终返回的行数。
  • Index lookup :表示 MySQL 使用索引 ecif_point_subjects_info_idx3 进行查找。索引字段包括 batch_date, batch_id, br_no, tx_br_no, dept_no, field2, bal_ind

3. 性能分析

  1. 索引选择

    • 查询使用了 ecif_point_subjects_info_idx3 索引,这是一个复合索引,包含了 batch_date, batch_id, br_no, tx_br_no, dept_no, field2, bal_ind 字段。
    • 由于查询条件中使用了 batch_datebatch_id,MySQL 能够快速定位到特定的分区和数据范围。
  2. 数据扫描量

    • 预计需要扫描 120 万行数据,这可能是因为查询条件虽然精确,但排序和分页操作导致 MySQL 需要扫描大量数据以找到所需的 5 行。
  3. 分页问题

    • 使用 LIMIT 500000, 5 导致 MySQL 需要扫描前 500,000 行数据,然后丢弃这些数据,只返回最后 5 行。这种分页方式在大数据量下效率较低。
  4. 优化建议

    • 减少扫描行数:可以通过优化查询条件或增加索引来减少需要扫描的行数。
    • 避免深分页:如果不需要深分页,可以考虑其他分页策略,如使用游标分页。
    • 索引优化:确保索引字段与查询条件和排序字段匹配,以减少排序和扫描的开销。

4. 总结

  • 查询效率:当前查询需要扫描大量数据(约 120 万行),并且使用了深分页,导致性能较低。
  • 优化方向:优化索引、减少扫描行数、避免深分页。
  • 建议:考虑使用游标分页或其他分页策略,以提高查询效率。同时,确保索引字段与查询条件和排序字段匹配,以减少排序和扫描的开销。
相关推荐
叫我阿龙啊7 分钟前
sysbench对linux服务器上mysql8.0版本性能压测
linux·mysql
悟能不能悟2 小时前
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
_代号00713 小时前
MySQL梳理二:索引
后端·mysql
匚WYHaovous14 小时前
SQL执行计划分析-分页查询
mysql