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_idx2
和ecif_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_date
和batch_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. 性能分析
-
索引选择:
- 查询使用了
ecif_point_subjects_info_idx3
索引,这是一个复合索引,包含了batch_date
,batch_id
,br_no
,tx_br_no
,dept_no
, field2,bal_ind
字段。 - 由于查询条件中使用了
batch_date
和batch_id
,MySQL 能够快速定位到特定的分区和数据范围。
- 查询使用了
-
数据扫描量:
- 预计需要扫描 120 万行数据,这可能是因为查询条件虽然精确,但排序和分页操作导致 MySQL 需要扫描大量数据以找到所需的 5 行。
-
分页问题:
- 使用
LIMIT 500000, 5
导致 MySQL 需要扫描前 500,000 行数据,然后丢弃这些数据,只返回最后 5 行。这种分页方式在大数据量下效率较低。
- 使用
-
优化建议:
- 减少扫描行数:可以通过优化查询条件或增加索引来减少需要扫描的行数。
- 避免深分页:如果不需要深分页,可以考虑其他分页策略,如使用游标分页。
- 索引优化:确保索引字段与查询条件和排序字段匹配,以减少排序和扫描的开销。
4. 总结
- 查询效率:当前查询需要扫描大量数据(约 120 万行),并且使用了深分页,导致性能较低。
- 优化方向:优化索引、减少扫描行数、避免深分页。
- 建议:考虑使用游标分页或其他分页策略,以提高查询效率。同时,确保索引字段与查询条件和排序字段匹配,以减少排序和扫描的开销。