初始化测试数据
创建一个测试用的表
create table dept( id int primary key auto_increment , deptName varchar(32) not null unique, salary decimal(12,6) not null, remark varchar(256), createDate date);
在表中插入一万条数据
BEGIN Declare i int default 0; while(i<=10000) do begin select i; set i=i+1; insert into dept(deptName,salary,createDate,remark) values(i,20000,now(),'test'); end ; End while; END
通过EXPLAIN分析SQL的执行计划
type:表示MySQL在表中找到所需行的方式,或者叫访问类型,常见类型如下(从左到右,性能由差到好)
ALL index range ref eq_ref const,system NULL
ALL: 全表扫描
index: 索引全扫描
range:索引范围扫描
ref:使用非唯一索引扫描
eq_ref:使用唯一索引扫描
const,system:单表中最多只有一个匹配行
以上:通过explain分析type是ALL 是性能最差的一种 以下:开始优化。
MySQL中BTREE索引的用法
普通的BTREE索引
优化前 explain select remark from dept where deptName = ?; type ALL
增加索引 ALTER TABLE dept ADD INDEX index_remark (`remark`);
优化测试 explain select remark from dept where deptName = ?; type ref
联合BTREE索引
增加联合索引 ALTER TABLE dept ADD INDEX index_all (`deptName`,`remark`,`createDate`);
explain select deptName,remark,createDate from dept where deptName='2' and remark = 'test'and createDate ='2018-07-22'; type ref
但是explain select deptName,remark,createDate from dept where remark = 'test'and createDate ='2018-07-22'; type index
——type从ref(使用非唯一索引扫描)变成了index(索引全扫描),
上面两个SQL 索引相同 Type不同是因为 BTREE索引中匹配最左前缀 比如给col1+col2+col3字段上加联合索引能够被包含
col1+col2 、col1+col2+col3、col1+col3使用(顺序没有影响 比如 where col1=? and col2=? 和 where col2=? and col1=? 结果一样)
使用联合索引 相当于一下子创建了如上的三个索引,这就是联合索引的好处
存在索引但不能使用索引的经典场景
例句:explain select deptName,remark,createDate from dept where deptName='2' and remark = 'test'and createDate ='2018-07-22'; type ref
下面是反面教材:
1.以%开头的LIKE查询不能使用BTREE索引
explain select deptName,remark,createDate from dept where deptName like'%2' and remark = 'test'and createDate ='2018-07-22'; type index
2.数据类型出现隐式转换时也不能使用索引
explain select deptName,remark,createDate from dept where deptName =2 and remark = 'test'and createDate ='2018-07-22'; type index
3.复合索引时 不符合最左匹配原则(上面已经提到)
explain select deptName,remark,createDate from dept where remark = 'test'and createDate ='2018-07-22'; type index
4.用or分隔开的条件,如果or前的条件中的列有索引,后面的列中没有索引,那么涉及到的索引都不会使用到
explain select deptName,remark,createDate from dept where deptName ='2' and remark = 'test'and createDate ='2018-07-22' or salary =200; type ALL
Order By语句
order by 字段混合使用DESC ASC 不会使用索引
select * from table order by key1 desc,key2 asc (尽量不要出现这种混合排序)
Where条件过滤的关键字和Order by中所使用的不同 不会使用索引
select * from table where key2 = ? order by key1 (order by 出现的关键字 尽量 在where条件中也出现)
优化Group By语句
当我们的SQL语句需要Group By分组时:
explain分析SQL的时候 Extra那一列有时候会出现 using Filesort表示需要额外的排序 如果业务没有要求排序 我们可以通过禁止排序, 加上 Order By NULL 有时候可以去掉using filesort
MySQL应不应该加唯一约束和外键约束
外键约束可以通过代码控制,加起来开发很不方便不建议加。如果业务需要唯一约束,因为唯一约束代码很难控制,必须加
对于唯一约束,有人说先查出来数据库已经存在的 再去判断传值存不存在。这样的缺点 1.查询所有已经存在的很费时间,2.需要考虑并发 不然重复数据还是会进入到数据库
一旦进入了错误数据 以后想加唯一约束都加不上了
查询语句关键字使用顺序: WHERE GROUP BY HAVING ORDER BY DESC LIMIT
补充
唯一索引
explain select deptName,remark,createDate from dept where id=2; type const 像这种利用唯一索引做where条件的效率最高(主键默认被加上了唯一索引)
SQL表连接查询时 表连接的条件(也就是外键)必须加索引(阿里巴巴代码规范看到的)
重要: 多表连接的时候 join on(a.id=b.id2) 连接外键id、id2 必须加索引。MySQL规定作为外键的字段必须有索引 也是为了让我们表连接的时候 用到索引(其实做到这点 基本上足够优化百分之八十的SQL了)