上节回顾:
1. 作用
优化查询,类似于书中的目录
2. 算法分类
Btree
Rtree
Hash
fulltext
gis
3. 聚集索引和辅助索引构成逻辑
4. 辅助索引细分
单列
多列(联合索引)
唯一
5. 索引树高度
1. 数据行 分表
2. 索引列值较长 前缀索引
3. 数据类型
6. 索引的管理操作
mysql> alter table t100w add index idx_k2(k2);
mysql> desc t100w
mysql> show index from t100w\G
mysql> alter table t100w add unique index idx_k1(k1);
mysql> alter table city add index idx_name(name(5));
mysql> alter table city add index idx_co_po(countrycode,population);
mysql> alter table city drop index idx_co_po;
7. 执行计划
7.1 作用
上线新的查询语句之前,进行提前预估语句的性能
在出现性能问题时,找到合理的解决思路
7.2 执行计划获取
mysql> desc select * from oldboy.t100w where k2='EF12'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t100w
partitions: NULL
type: ref
possible_keys: idx_k2
key: idx_k2
key_len: 17
ref: const
rows: 293
filtered: 100.00
Extra: NULL
1 row in set, 1 warning (0.00 sec)
table: t100w
type: ref 索引的应用级别
possible_keys: idx_k2 可能会使用到的索引
key: idx_k2 实际上使用的索引
key_len: 17 联合索引覆盖长度
rows: 293 查询的行数(越少越好)
Extra: NULL 额外的信息
7.3 执行计划的分析
type 索引的应用级别
ALL : 全表扫描,不走索引
没建立索引!!
建立索引不走的()!!!!
mysql> desc select * from t100w;
mysql> desc select * from t100w where k1='aa';
(辅助索引)
mysql> desc select * from t100w where k2 != 'aaaa';
mysql> desc select * from t100w where k2 like '%xt%';
Index :全索引扫描
mysql> desc select k2 from t100w;
range :索引范围扫描
辅助索引 : > < >= <= like , in or
主键: !=
mysql> desc select * from world.city where countrycode like 'C%'
mysql> desc select * from world.city where id!=3000;
mysql> desc select * from world.city where id>3000;
mysql> desc select * from world.city where countrycode in ('CHN','USA');
改写为:
desc
select * from world.city where countrycode='CHN'
union all
select * from world.city where countrycode='USA';
ref : 辅助索引等值查询
mysql> desc select * from city where countrycode='CHN';
eq_ref :在多表连接查询是on的条件列是唯一索引或主键
mysql> desc select a.name,b.name ,b.surfacearea
from city as a
join country as b
on a.countrycode=b.code
where a.population <100;
const,system : 主键或唯一键等值查询
mysql> DESC SELECT * from city where id=10;
Extra: NULL 额外的信息
using filesort
mysql> alter table city add index idx_co_po(countrycode,population);
7.4 explain(desc)使用场景(面试题)
题目意思: 我们公司业务慢,请你从数据库的角度分析原因
1.mysql出现性能问题,我总结有两种情况:
(1)应急性的慢:突然夯住
应急情况:数据库hang(卡了,资源耗尽)
处理过程:
1.show processlist; 获取到导致数据库hang的语句
2. explain 分析SQL的执行计划,有没有走索引,索引的类型情况
3. 建索引,改语句
(2)一段时间慢(持续性的):
1. 记录慢日志slowlog,分析slowlog
2. explain 分析SQL的执行计划,有没有走索引,索引的类型情况
3. 建索引,改语句
8. 索引应用规范
业务
1.产品的功能
2.用户的行为
"热"查询语句 --->较慢--->slowlog
"热"数据
8.1 建立索引的原则(DBA运维规范)
8.1.0 说明
为了使索引的使用效率更高,在创建索引时,必须考虑在哪些字段上创建索引和创建什么类型的索引。
那么索引设计原则又是怎样的?
8.1.1 (必须的) 建表时一定要有主键,一般是个无关列
略.回顾一下,聚集索引结构.
8.1.2 选择唯一性索引
唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。
例如,学生表中学号是具有唯一性的字段。为该字段建立唯一性索引可以很快的确定某个学生的信息。
如果使用姓名的话,可能存在同名现象,从而降低查询速度。
优化方案:
(1) 如果非得使用重复值较多的列作为查询条件(例如:男女),可以将表逻辑拆分
(2) 可以将此列和其他的查询类,做联和索引
select count(*) from world.city;
select count(distinct countrycode) from world.city;
select count(distinct countrycode,population ) from world.city;
8.1.3(必须的) 为经常需要where 、ORDER BY、GROUP BY,join on等操作的字段,
排序操作会浪费很多时间。
where A B C ----》 A B C
in
where A group by B order by C
A,B,C
如果为其建立索引,优化查询
注:如果经常作为条件的列,重复值特别多,可以建立联合索引。
8.1.4 尽量使用前缀来索引
如果索引字段的值很长,最好使用值的前缀来索引。
8.1.5 限制索引的数目
索引的数目不是越多越好。
可能会产生的问题:
(1) 每个索引都需要占用磁盘空间,索引越多,需要的磁盘空间就越大。
(2) 修改表时,对索引的重构和更新很麻烦。越多的索引,会使更新表变得很浪费时间。
(3) 优化器的负担会很重,有可能会影响到优化器的选择.
percona-toolkit中有个工具,专门分析索引是否有用
8.1.6 删除不再使用或者很少使用的索引(percona toolkit)
pt-duplicate-key-checker
表中的数据被大量更新,或者数据的使用方式被改变后,原有的一些索引可能不再需要。数据库管理
员应当定期找出这些索引,将它们删除,从而减少索引对更新操作的影响。
8.1.7 大表加索引,要在业务不繁忙期间操作
8.1.8 尽量少在经常更新值的列上建索引
8.1.9 建索引原则
(1) 必须要有主键,如果没有可以做为主键条件的列,创建无关列
(2) 经常做为where条件列 order by group by join on, distinct 的条件(业务:产品功能+用户行为)
(3) 最好使用唯一值多的列作为索引,如果索引列重复值较多,可以考虑使用联合索引
(4) 列值长度较长的索引列,我们建议使用前缀索引.
(5) 降低索引条目,一方面不要创建没用索引,不常使用的索引清理,percona toolkit(xxxxx)
(6) 索引维护要避开业务繁忙期
8.2 不走索引的情况(开发规范)
8.2.1 没有查询条件,或者查询条件没有建立索引
select * from tab; 全表扫描。
select * from tab where 1=1;
在业务数据库中,特别是数据量比较大的表。
是没有全表扫描这种需求。
1、对用户查看是非常痛苦的。
2、对服务器来讲毁灭性的。
(1)
select * from tab;
SQL改写成以下语句:
select * from tab order by price limit 10 ; 需要在price列上建立索引
(2)
select * from tab where name='zhangsan' name列没有索引
改:
1、换成有索引的列作为查询条件
2、将name列建立索引