1、MySQL第一章,索引优化

原创
2017/08/09 09:42
阅读数 149

1、MySQL第一章,索引优化

一、数据库性能下降的原因

两方面原因:执行时间长、等待时间长

1)、select语句写的烂

2)、索引失效(索引就是预先检索和排序)(单值、复合 )

3)、关联查询,太多join(设计原因)

4)、服务器调优、各个参数的设置(缓冲、线程数等)

二、SQL执行顺序

FROM ON JOIN WHERE GROUP BY HAVING SELECT DISTINCT ORDER BY LIMITE

三、索引分类

1)、单值索引--单个列

2)、唯一索引--索引列的值必须唯一,但允许有空

3)、复合索引--一个索引包含多个列

四、基本语法

创建 create 【unique】 index [indexName] on [tableName] (columnName)

创建 alter table [tableName] add 【unique】index [indexName] (columnName)

删除 drop index [indexName] on [tableName]

查看 show index from [tableName]

(索引建的多了:增删改会变慢)

五、索引结构

BTree Hash Full-Text全文索引 R-Tree

六、适合创建索引的情况

1)、主键自动创建唯一索引

2)、频繁作为查询条件的字段

3)、查询中与其他表关联的字段,外键关系创建索引

4)、频繁更新的字段不适合创建索引

5)、where条件中用不到的字段不需要创建索引

6)、和单值索引相比最好创建组合索引

7)、查询中排序字段,排序字段若通过索引去访问将大大提高排序速度

8)、查询中统计和分组的字段

七、不适合创建索引的情况

1)、表记录太少

2)、经常增删改的表的字段

3)、字段中数据差异率和重复率不高、没必要创建索引(例如民族、国际、性别)

八、explain

1)、表的读取顺序

2)、数据读取操作的操作类型

3)、那些索引可以使用

4)、那些索引被实际使用

5)、表之间的引用

6)、每张表有多少行被优化器查询

id type key是关键的衡量指标

8.1、explain之id

表示执行select子句或操作表的顺序

1)、id相同:执行顺序由上而下

img

2)、id不同:id值越大优先级越高,越先被执行。

img

3)、id相同和不同同时存在:id相同的可以认为是一组的由上至下执行,id不同的越大优先级越高,越先执行

img

8.2、explain之select_type

表示查询类型:用于区分普通查询、联合查询、子查询等

1)、simple:不包含任何子查询或union

2)、primary:查询中若包含任何复杂的子部分,最外层查询则被标记为primary(同subquery同时存在)

3)、subquery

4)、derived衍生:(临时表?)

5)、union

6)、union result:(union合并的结果集)

8.3、explain之table

表示查询中所使用到的表

8.4、explain之type

查询类型排序:

从最好到最差的顺序依次是:system>const>eq_ref>ref>range>index>all

一般来说达到range和ref级别就好

1)、system:表只有一行记录(等于系统表),const类型的特例,平时不会出现,可以忽略不计

2)、const:表示用过索引依次就可找到,用于比较primary key或unique索引。应为只匹配一行数据,所以查询很快。

3)、eq_ref:唯一索引扫描,对于每个索引建,表中只有一条记录与之匹配,常见于主键或唯一索引扫描

img

4)、ref

img

5)、range

img

6)、index full index scan,index与all的区别是index只遍历索引树,通常比all快。

img

7)、all

8.5、explain只possible_keys和key介绍

possible_key显示可能应用到这张表中的索引(一个或多个)---查询字段上存在索引,则该索引被列出(不一定被使用)

key显示实际使用的索引,如果为NULL,则没有使用任何索引---查询中若出现覆盖索引,则该索引出现在key列表中

(覆盖索引:select的字段和索引中所使用的字段一致)

img

8.6、key_len

表示索引中使用的字节数(使用的索引的长度),在不损失精确性的情况下,长度越短越好

img

8.7、ref

显示索引的那一列被使用了,如果可能的话,最好是一个常数,那些列或常量被用于查找索引列上的值

img

img

8.8、rows

根据表统计信息和索引选用情况,大致估算出找到所需记录所需读取的行数。

img

8.9、extra

十分重要的额外信息

(1)、using filesort:mysql会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取(文件排序)---自己重新排序

(最好不要出现using filesort)

img

(2)、using temporary:新建了内部的临时表保存临时结果,常见于order by和group by

(十死一生,千万不要出现)

img

img

(3)、using index:使用索引默认的排序

表示相应的select操作中使用了覆盖索引,避免访问了表的数据行,效率不错

如果同时出现using where,表明索引被用来索引键值的查找

如果没有同时出现using where,表明索引被用来读取数据而非执行查找动作

(这种情况非常好,不用再排序了)

img

img

img

(4)、using where:使用了where过滤(去表里边检索,而非索引里边---查询字段里包含索引列中不存在的字段)

(5)、using join buffer:使用了连接缓存

(6)、impossible where:表示where后的查询条件为FALSE不能获取任何值(如:name="a" and name="b")

九、索引案例:

range后的索引会失效,解决:将range的字段从索引中删去

(1)单表优化

(2)两表优化

left join right join 将索引建立在副表上(比如:A left join B就应该把索引建立在B上)

注意:

Join语句优化:

(1)、尽量减少join语句中的循环总次数:-----永远用小的结果集去驱动大的结果集

(2)、有子查询,优先优化内层循环

(3)、保证join语句中被驱动表上的join条件字段已经被索引。

十、索引的优化 以及 如何避免索引失效

索引失效情况

img

10.1、最佳左前缀法则

如果索引了多列,要遵循最左前缀法则。指的是查询从最左前列开始并且不能跳过索引中的列:

如:建立索引的顺序是NAME AGE POS

where 后 是 AGE POS 丢失了NAME索引会失效,即左边的列不能丢失,且顺序不能变

口诀(带头大哥不能死)

如果where后是 NAME POS,索引索然存在,但只是部分使用,即只有NAME会使用到索引,AGE的索引丢失

口诀(中间兄弟不能丢)

img

img

10.2、不要在索引列上做任何操作

(操作如:计算、函数、自动或手动的类型转换等,会导致索引失效而转向全表扫描)

口诀:索引列上少操作

img

10.3、范围之后全失效

(即 范围类型的索引列后边的索引列字段 全部失效)

口诀:范围之后全失效

img

(NAME AGE都用到了索引,但是POS的索引失效)

10.4、尽量使用覆盖索引(索引列和查询列一致),减少 select * 使用

img

img

10.5、MySQL在使用不等于(!=或<>)的时候无法使用索引,会导致全表扫描

img

10.6、IS NULL或IS NOT NULL也无法使用索引

img

10.7、like以通配符开头(‘%abc’)MySQL索引失效,会变成全表扫描

口诀:like%加右边,两边%用覆盖

img

img

(like查询如果在右边写%,会变成范围range查询----但这个range和普通的range不一样,这个range后边的索引字段不会失效)

注:

如何解决like ‘%ABC%’导致索引失效?

用覆盖索引代替 * 可以防止索引失效

img

10.8、字符串不加单引号索引失效

img

10.9、少用or,用它来连接时会导致索引失效

img

索引练习:

img

img

只要where里有 顺序变没问题

img

img

十一、面试题分析

1、查询顺序变化,索引不会失效

img

2、范围之后全失效

img

3、c3用于了排序,断了所以C4的索引没有用到

img

4、C1、C2用到了索引,但跳过了C3,所以C4的排序会造成 查找到记录后,重新排序的额外损失

img

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
1 收藏
0
分享
返回顶部
顶部