01、什么是索引

数据库索引,是数据库管理系统(DBMS)中一个排序的数据结构,以协助快速查询、更新数据库表中数据。

mysql添加非唯一索引 mysql 非唯一索引_mysql添加非唯一索引

索引类型

普通(Normal):也叫非唯一索引,是最普通的索引,没有任何的限制。

唯一(Unique):唯一索引要求键值不能重复。另外需要注意的是,主键索引是一种特殊的唯一索引,它还多了一个限制条件,要求键值不能为空。主键索引用primaykey创建。 

全文(Fulltext):只有文本类型的字段才可以创建全文索引,比如char、varchar、text。

全文(Fulltext)使用?

SELECT * FROM `student` WHERE MATCH(`name`,`address`) AGAINST('聪 广东')

建议在此多列数据上创建一个联合的全文索引,否则使用不了索引的。

02、InnoDB逻辑存储结构

mysql添加非唯一索引 mysql 非唯一索引_mysql添加非唯一索引_02

 

mysql添加非唯一索引 mysql 非唯一索引_主键_03

mysql添加非唯一索引 mysql 非唯一索引_主键_04

03、索引的结构

多路平衡查找树(BTree)(分裂、合并)

mysql添加非唯一索引 mysql 非唯一索引_子节点_05

B+树(加强版多路平衡查找树)

mysql添加非唯一索引 mysql 非唯一索引_mysql添加非唯一索引_06

MySQL中的B+Tree有几个特点:

1、它的关键字的数量是跟路数相等的;

2、B+Tree的根节点和枝节点中都不会存储数据,只有叶子节点才存储数据。

比如我们搜索id=28,虽然在第一层直接命中了,但是全部的数据在叶子节点上面,所以我还要继续往下搜索,一直到叶子节点。

3、B+Tree的每个叶子节点增加了一个指向相邻叶子节点的指针,它的最后一个数据会指向下一个叶子节点的第一个数据,形成了一个有序链表的结构。

4、它是根据左闭右开的区间[   )来检索数据

总结:InnoDB采用的是B+ Tree

04、InnoDB和MyISAM的索引结构

InnoDB的表有两个文件(.frm和.ibd)

MyISAM的表有三个文件(.frm、.MYD、.MYI)

mysql添加非唯一索引 mysql 非唯一索引_mysql添加非唯一索引_07

mysql添加非唯一索引 mysql 非唯一索引_mysql添加非唯一索引_08

【1】、聚集索引(聚簇索引)?

索引键值的逻辑顺序跟表数据行的物理存储顺序是一致的。比如:主键索引是聚集索引,非主键都是非聚集索引。

【2】、辅助索引

 主键之外的索引,比如我们在name字段上面建的普通索引。

mysql添加非唯一索引 mysql 非唯一索引_子节点_09

【3】、如果一张表没有主键怎么办?

InnoDB会选择第一个不包含有NULL值的唯一索引作为主键索引。

如果也没有这样的唯一索引,则InnoDB会选择内置6字节长的ROWID作为隐藏的聚集索引,它会随着行记录的写入而主键递增。

04、索引的使用原则

【1】、列的离散度

count(distinct(column_name)):count(*)。分子越大,列的离散度就越高。

【2】、联合索引最左匹配

按照从左到右的顺序来建立搜索树的

比如:使用where name='xxx' and phone='136xx'去查询数据的时候,B+Tree会优先比较name来确定下一步应该搜索的方向,往左还是往右。如果name相同的时候再比较phone。但是如果查询条件没有name,就不知道第一步应该查哪个节点,因为建立搜索树的时候name是第一个比较因子,所以用不到索引。

mysql添加非唯一索引 mysql 非唯一索引_主键_10

【3】、创建联合索引

CREATE INDEX  idx_name_phone on user_innodb(name,phone);

我们创建三个字段的索引index(a,b,c),相当于创建三个索引:

index(a)

index(a,b)

index(a,b,c)

【4】、覆盖索引

回表:

非主键索引,先通过索引找到主键索引的键值,再通过主键值查出索引里面没有的数据。比主键索引的查询多扫描了一棵索引树。这个过程就叫回表。

mysql添加非唯一索引 mysql 非唯一索引_数据_11

如何避免回表?

select的数据列只用从索引中就能够取得,不必从数据区中读取,这时候使用的索引就叫做覆盖索引,这样就避免了回表。

如:

SELECT  name,phone

【5】、索引条件下推

05、索引的总结

建立索引

1、用于where判断order排序和join的(on)字段上创建索引

2、索引的个数不要过多。

3、区分度低的字段,例如性别,不要建索引。

4、组合索引把散列性高(区分度高)的值放在前面。

5、不建议用无序的值(例如身份证、UUID)作为索引

执行过程中不使用索引

1、索引列上使用函数

如:where id+1=4;

2、字符串不加引号,出现隐式转换

where name = 136;

wherename = '136';

3、like条件中前面带%

4、负向查询

NOT LIKE

!=(<>)和NOT IN