ENV
- 线上环境为RDS,版本5.7.15
select version()
output:
5.7.15-log
- 测试环境为docker搭建的mysql,版本5.7.19
select version()
output:
5.7.19
- 单表3000万+的class表以及20万+的学校表,需要使用count查询实时数量用于分页,延迟不能太高,否则影响业务
- 因需要使用事务功能,使用存储引擎为Innodb(MyISAM count是自动计数单独保存,Innodb需要每次扫描表进行统计)
- 本文使用class表进行示例表述,school同理
OPTIMIZE
一. 出现的第一个问题是RDS线上mysql的查询速度始终没有测试库的快,相同的数据和存储结构,索引数据都相同(一开始线上使用count完全不能查询,会出现等待超时).
1. 查看索引
show index from consumer.class;
output:
'class', '0', 'PRIMARY', '1', 'id', 'A', '28663646', NULL, NULL, '', 'BTREE', '', ''
'class', '0', 'UQE_class_loginName', '1', 'loginName', 'A', '28663646', NULL, NULL, 'YES', 'BTREE', '', ''
'class', '1', 'IDX_class_school_id', '1', 'school_id', 'A', '211268', NULL, NULL, '', 'BTREE', '', ''
'class', '1', 'grade_id', '1', 'grade_id', 'A', '8644', NULL, NULL, 'YES', 'BTREE', '', ''
'class', '1', 'schuid', '1', 'schuid', 'A', '216557', NULL, NULL, 'YES', 'BTREE', '', ''
2. 测试时间
set profiling = 1;
SELECT count(*) FROM consumer.class;
show profiles;
3. 分别分析sql的执行
explain select count(*) from consumer.class ;
test output:
'1', 'SIMPLE', 'class', NULL, 'index', NULL, 'IDX_class_school_id', '4', NULL, '28663646', '100.00', 'Using index'
online output:
1
1
SIMPLE
null
null
null
null
null
null
null
null
null
Select tables optimized away
发现线上版本的mysql是经过自己编译器优化的Select tables optimized away,但是效率确实低到不能接受(单独这样查询几分钟过后仍然查不出来,并且显示超时),这是因为mysql5.7.*版本机制相关的问题,具体可参考:
https://bugs.mysql.com/bug.php?id=80580
https://stackoverflow.com/questions/27377549/select-count-not-using-index
4. 强制使用索引,解决了上面线上查询几分钟仍不能查询到结果后返回超时的问题
select count(`id`) from consumer.class force index(primary) where id > 0
explain