MySQL优化一般是需要索引优化、查询优化、库表结构优化三驾马车齐头并进。
可以说,索引优化是对查询性能优化最有效的手段,索引能够轻易将查询性能提高几个数量级,“最优”的索引有时比一个“好的”索引性能要好几个数量级。创建一个真正“最优”的索引经常需要重写查询,所以索引优化和查询优化的关系很紧密。
本文是《千万级大数据查询优化》系列第一篇:创建高性能的索引。
我们先从一个面试题开始。
面试题:
如果有四条sql语句,查询条件分别是
where A=1 and B=1 and C=1.
where A=1 and B=1.
where A=1 and C=1.
where B=1 and C=1.
问该怎么设计索引?
四位求职者回答:
第一个求职者回答到:需要创建3个组合索引(a, b, c)(a, c)(b, c);
第二个求职者回答:也是需要3个组合索引(a, b)(b, c)(a, c);
第三个求职者回答:只需要2个组合索引(a, b, c)(b, c);
第四个求职者回答:这个要看索引的区分度是怎么样,如果ab区分度都很好,单独idx_a和idx_b,普通情况idx_abc和idx_bc。
看完四位求职者的回答,你的答案是什么呢?
上面的面试题涉及到的知识是多列索引的创建和选择合适的索引列顺序,我们先创建一个表进行测试。
# 创建数据表
create table tb_test_1(
id smallint unsigned auto_increment primary key,
AAA varchar(100) not null,
BBB varchar(100) not null,
CCC varchar(100) not null,
DDD varchar(100) not null
);
# 插入数据,执行几十次
INSERT INTO tb_test_1 VALUES
(null, CONCAT(‘aaa‘, ROUND(RAND()*1)), CONCAT(‘bbb‘, ROUND(RAND()*1)), CONCAT(‘ccc‘, ROUND(RAND()*1)), CONCAT(‘ddd‘, ROUND(RAND()*1))),
(null, CONCAT(‘aaa‘, ROUND(RAND()*10)), CONCAT(‘bbb‘, ROUND(RAND()*10)), CONCAT(‘ccc‘, ROUND(RAND()*10)), CONCAT(‘ddd‘, ROUND(RAND()*10))),
(null, CONCAT(‘aaa‘, ROUND(RAND()*100)), CONCAT(‘bbb‘, ROUND(RAND()*100)), CONCAT(‘ccc‘, ROUND(RAND()*100)), CONCAT(‘ddd‘, ROUND(RAND()*100))),
(null, CONCAT(‘aaa‘, ROUND(RAND()*1000)), CONCAT(‘bbb‘, ROUND(RAND()*1000)),