索引是数据结构;可以简单理解为书的目录,通过目录找书本章节的内容,顺序结构
索引分类
- 普通索引:只有一个索引只包含一个列,一个表可以有多个单列索引 
- 唯一索引(Unique):索引列的值必须唯一,但允许有空值 
- 复合索引:即一个索引包含多个列 
- 聚簇索引:并不是一种单独的索引类型,而是一种数据存储方式。具体细节取决于不同的实现,InnoDB的聚簇索引其实就是在同一个结构中保存了B-Tree索引(技术上来说就是B+Tree)和数据行。 
- 非聚簇索引:不是聚簇索引就是非聚簇索引 
查看索引:
| 1 | show index from 表名; | 
创建索引:
| 1 | CREATE UNIQUE INDEX 索引名 ON 表名(字段名); | 
| 1 | ALTER TABLE 表名 add UNIQUE 索引名(字段名); | 
删除索引:
| 1 | DROP INDEX 索引名 ON 表名; | 
执行计划
执行计划是什么:使用explain关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的。分析你的查询语句或是表结构的性能瓶颈。
比如查看一条SQL的执行计划,
| 1 | EXPLAIN SELECT * FROM grade WHERE course = "语文" | 
会展示如下信息
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | 
|---|---|---|---|---|---|---|---|---|---|
| 1 | SIMPLE | grade | ref | index_course | index_course | 69 | const | 3 | Using index condition | 
id:一个序号值,按顺序从大到依次执行
select_type:选择的类型,可选值有: SIMPLE(简单的),
table:查询的表
type:访问类型,主要包括以下几种:
访问速度如表格显示从上到下排列由慢到快;通过这个属性可以直接判断是否走索引
| 类型 | 解释 | 
|---|---|
| ALL | 全表扫描 | 
| index | 索引扫描 | 
| range | 范围扫描 | 
| ref | 非唯一索引扫描 | 
| eq_ref | 唯一索引扫描 | 
| const | 常数引用 | 
possible_keys:可能走的索引
key:SQL实际用到的索引,用到什么索引,key会显示索引名
key_len:表示索引使用的字节数,索引长度,可以衡量索引是否生效,
比如如下SQL会查出key_len为13,
| 1 | explain select * from t1 where col1 = 'ab'; | 
如果如下SQL会查出key_len为26,说明用了两个索引
| 1 | explain select * from t1 where col1 = 'ab' and col2 = 'cd'; | 
ref:表示哪一列用到了索引
rows:扫描行数
Extra:额外的信息说明
优化实战
- 全职匹配 
- 最佳左前缀法则:如果索引是多个,要遵循此原则。指的是查询从索引的最左边开始并且不跳过字段。如果聚合索引是name,age,postion三个字段的聚合索引;那如果通过age和postion查询,那索引会失效,因为name头不在了,无法走索引 
- 不能再索引列上做任何操作(计算,函数),会跳过索引 
- 范围条件放最后:存储引擎不能使用索引中范围条件右边的列; 
 比如如下SQL只会走name和age两个索引,因为age做了范围搜索之后就不在进入索引- 1 - select * from staffs where name = '张三' and age >15 and postion = '上海', 
- 尽量使用覆盖索引:只访问索引的查询,减少“select ”的; 
 比如只查询name,age,postion三个参数,
 那就不要用select * from~ 而是 select name,age,postion from staffs where~
- 不等于要慎用:mysql在使用不等于(!=或<>)的时候无法使用索引,会导致全表扫描; 
 如下无法使用索引- 1 - select * from staffs where name != '张三'; 
如下使用了上面的覆盖索引原则,这样可以使用索引
| 1 | select name,age,postion from staffs where name != '张三'; | 
- Null/Not有影响 : select * from staffs where name is not null; 是否会全表扫描要根据字段来决定;如果查询的字段没有设置为 not null那就不会全表扫描 
- Like查询要当心:左模糊查询会造成全表扫描,避免使用左模糊查询;但是实际项目无法避免,所以要用到之前的覆盖索引原则 
- 字符串不加单引号索引失效:如果数据类型是varchar那一定要在查询条件上加上引号;如果不用引号那就会全表扫描 
- OR改UNION效率高:能用union就不要用or,用or会导致索引失效