索引是什么?

索引是帮助MySQL高效获得数据的数据结构。

即:索引是一种数据结构。

可以理解为一种排好序的快速查找数据结构

索引的目的

目的是提高搜索效率,类似字典

索引的底层实现

B Tree

B+Tree

full-text

Hash

R-Tree

一般默认为B树(多路查找树 + 链表)

索引适合的场景

多查询,少修改的场景

查询时:假如我们对数据库中的某一个字段建立了索引,我们下次需要对此字段进行查询时,直接从索引中,去查询,避免从无序的全表进行查询加快了查询速度

修改时:假如我们对数据库中的某一个字段建立了索引,我们下次需要对数据库进行修改时,我们在更改数据库中的真实数据的同时,还需要去修改对应的索引,使索引指向正确

索引分类

单值索引

对数据库表中的单个字段建立索引

唯一索引

建立的索引的字段是候选键(即:建立索引的字段的值在表中不重复)

复合索引

对数据库表中的多个字段建立索引

哪些情况需要建立索引?

1、 主键自动建立索引

2、 频繁作为查询条件的字段应该创立

3、 查询中与其他表关联的字段,外键应该建立索引

4、 频繁更新的字段不应该建立索引

5、 where条件中用不到的数据不应该建立索引

6、 单值索引与组合索引?优先创建组合索引

7、 查询中排序的字段

8、 查询中统计或者分组的字段

哪些情况不需要建立索引?

1、 经常增删改的表

2、 数据重复且分布平均的字段

如何分析SQL

1、 Explain + SQL语句

* ID: 优先执行ID大的字段,ID相同按顺序执行

* select\_type

* SIMPLE 简单的SQL查询

* PRIMARY 复杂查询的最外层为PRIMARY

* SUBQUERY 子查询

* DERIVED 衍生查询(临时表)

* UNION 联合查询的后面那一个SELECT

* UNION RESULT 对联合查询的结果进行SELECT

* table:表的来源

* type:查询类型,由最优到最差的排序有:

* system 表只有一行记录(系统表),这是const的特例,平时不会出现,忽略不计

* const 直接对主键或者Unique索引进行查询(唯一索引,主键自动建立唯一索引)

* eq\_ref (唯一性索引扫描)联表对主键或者Unique索引进行查询对于每个索引键,表中只有一条记录与之匹配

* ref (非唯一性索引扫描)返回匹配单独值的所有行,也是对索引进行扫描,但是索引值可能出现重复

* range 对索引进行范围性检索,在where语句中使用between、、in等查询,这种扫描开始于索引某一点,结束于另一点,不用进行全局扫描

* index 扫描全部的索引树

* ALL 全表扫描

* possible\_keys 可能用到的索引

* key 实际使用的索引,若为NULL则没有使用

覆盖索引:possible\_keys中没有的,而key中出现

* key\_len 索引中使用的字节数,通过该列计算查询中使用的索引长度,在不丢失精度的情况下,越小越好,显示的是最大可能长度,而非是实际使用长度

* ref 显示索引上的值哪一列被使用了,如果可能的话,是一个常数。哪些列或常数被用于查找索引列上的值

* rows 每张表有多少行被优化器查询

* extra

* filesort 文件外排序,没有利用到索引去排序

* temporary 使用临时表排序,没有利用到索引

* index 表示相应的查询语句使用了覆盖索引(查询字段在该索引范围内,则该索引为覆盖索引),避免访问了表的数据行,效率高。(当索引被拿来进行执行索引的查找,则会多一个using where,没有using where则表示直接读取了索引的数据,没有进行查找)

索引失效案例与解决方案

case1: 单表范围查询导致复合索引失效

SQL语句:

假如我们建立了一个复合索引包含A、B、C三个字段,但是我们对第二个字段为范围查询,则会导致C字段不能使用索引进行排序,出现了filesort,使得SQL速度变慢

解决方法: 删除原来的索引,建立一个AC字段的索引,

case2: 索引两表连接优化

表连接的情况下

这类情况,应该给较少数据量的那一边建立索引,可以较好地提高效率。(即:给 tb_B 表建立索引)

左连接:给右边加索引

右连接:给左边加索引

case 3: 索引三表连接优化

这类情况可以把表分解拆分成两表的形式分析(给tb_B加索引,与给t b_C加索引)

case将持续更新……欢迎大家补充

JOIN优化

尽量减少nestedloop的循环次数(小表驱动大表

优先优化nestedloop的内层循环

保证被驱动表上的Join字段已经被索引

当无法保证被驱动表的Join字段被索引且内存充足的情况下,不要太吝啬JoinBuffer的设置

#