背景
单表数据量:200万+;
sql
EXPLAIN SELECT
IFNULL(SUM(IF(jfm.direction = 1, jfm.fee, - jfm.fee)), 0) AS numDouble,
jfm.managerId as managerId
FROM kd_finance_manager jfm
WHERE
jfm.payTime >= '2022-04-25 00:00:00' and jfm.payTime <= '2022-05-01 23:59:59' and
jfm.financeType = 1
group by jfm.managerId
ddl
create table kd_finance_manager
(
financeId bigint auto_increment comment ‘财务ID’
primary key,
managerId bigint not null comment ‘代理商ID’,
orderId bigint not null comment ‘订单ID 财务类型为1.关联消费订单 2.关联提现订单’,
orderNo varchar(50) not null comment ‘订单业务编号’,
balance decimal(16, 2) default 0.00 null comment ‘当前余额(交易前的余额,即当前余额+交易金额= 最新余额)’,
fee decimal(16, 2) default 0.00 null comment ‘费用’,
financeType tinyint unsigned default ‘1’ null comment ‘财务类型:1.共享订单 2.提现订单’,
direction tinyint unsigned default ‘1’ null comment ‘资金去向:1.收益 2.支出’,
payTime datetime null comment ‘订单支付时间’,
createManagerId bigint null comment ‘创建人id’,
createManagerName varchar(100) null comment ‘创建人名称’,
createDateTime datetime null comment ‘创建时间’,
remark varchar(255) null comment ‘备注’
)
comment ‘代理商交易明细表’ charset = utf8;
create index idx_kd_finance_manager_orderno
on kd_finance_manager (orderNo);
create index index_direction
on kd_finance_manager (direction);
create index index_financeType
on kd_finance_manager (financeType);
create index index_managerId
on kd_finance_manager (managerId);
create index index_orderId
on kd_finance_manager (orderId);
create index index_payTime
on kd_finance_manager (payTime);
sql 执行计划
可以看到索引走的是index_financeType ,扫描的行数1333106行
我们强制走index_payTime索引,对应的执行计划:
可以看到,mysql 优化后索引的走index_financeType 扫描行数133万+,强制走了索引index_payTime后扫描行数99万,因此mysql索引优化不一定能找到最优方案,我们需要根据实际情况来选择对应的索引,但绝大部分情况下mysql的优化是最优的
实际执行情况
走mysql自己选择的索引执行情况:
强制索引执行情况:
可以看到mysql优化的索引需要61s,强制选择索引只需要2s