第六十四篇 索引

1、什么是索引

1.在关系型数据库中,索引是一种单独的、物理层面的对数据表中一列或多列的值进行排序的一种存储结构,也称之为keysql

2.能够理解:搜索引导,索引是一个特殊的数据结构,其存储的是数据的关键信息与详细信息的位置关系,例如:图书的目录,能够根据目录中的页码快速找到所需的内容数据库

3.有三种索引:unique key、primary key、index key数据结构

2、为何须要索引

加速查询,当数据量很是大的时候,查询某一个数据集是很是慢,索引是提高查询效率最有效的手段测试

3、索引的影响:

1.注意:在数据库中插入数据会引起索引的重建优化

2.不是说有了索引就能加速,得看你的查询语句有没有正确使用索引操作系统

3.索引也须要占用额外的数据空间设计

4.添加索引后将致使增减删除修改变慢(写入)code

4、什么样的数据应该添加索引:

1.查询操做较多,写入较少而且数据量很大时视频

2.查询与写入操做的占比为 10:1 ,或者查询更多时

5、索引的实现原理

1.相关知识

1.数据库的索引,实现思路与字典是一致的,须要一个独立的存储结构,专门存储索引数据

2.本质上索引是经过不断缩小查询范围来提升查询效率

2.磁盘io

1.平均查找一个数据须要花费至少9.15ms,这段时间CPU就会切换到其余的程序

2.操做系统预读取:当一次io时,不光把当前磁盘地址的数据读取,而是把相邻的数据也都读取到内存缓冲区中,这个理论对于索引的数据结构设计很是有帮助

3.咱们要加速查询,必须减小io操做的次数

3.索引数据结构

1.b+树(第一层为根节点只能有一个,中间层为分支节点,最下面的是叶子节点,当叶子节点过多时,分支节点势必也会相应的增长,上面的根节点也就须要多个,因为根节点有且只有一个的特性,所以只能增长层数,那么查询时遇到的io操做也就相应的增长了,影响效率):

2.在b+树种,叶子节点才是存储真实数据的,叶子数量越多,树的层级越高,进而致使io操做增长(一层一个io操做)

3.要避免这个问题,在叶子节点中尽量的存储更多的数据,应该将数据量小的字段做为索引

4.最左匹配原则:

1.当b+树的数据项是复合的数据结构,好比(name,age,sex)的时候(多字段联合索引),b+树会按照从左到右的顺序来创建搜索树,好比当(张三,20,F)这样的数据来检索的时候,b+树会优先比较name来肯定下一步的所搜方向,若是name相同再依次比较age和sex,最后获得检索的数据;但当(20,F)这样的没有name的数据来的时候,b+树就不知道下一步该查哪一个节点,由于创建搜索树的时候name就是第一个比较因子,必需要先根据name来搜索才能知道下一步去哪里查询。好比当(张三,F)这样的数据来检索时,b+树能够用name来指定搜索方向,但下一个字段age的缺失,因此只能把名字等于张三的数据都找到,而后再匹配性别是F的数据了, 这个是很是重要的性质,即索引的最左匹配特性

2.索引在查找时,是按照从左往右依次比较,若是查询语句没有出现最左边的索引,将没法加速查询

5.汇集索引:

1.汇集索引种包含了全部字段的值,若是已指定了主键,主键就是汇集索引,若是没有则找一个非空且惟一的字段做为汇集索引,若是连这个也找不到,则自动生成一个字段做为汇集索引

2.汇集索引中存储了全部的数据

6.辅助索引

1.除了汇集索引之外的都叫作辅助索引,包括foreign keyunique

2.辅助索引中只包含当前的索引字段和主键的值

7.覆盖查询

1.指的是在当前索引结构中就能找到全部须要的数据,若是使用的是汇集索引来查询那么必定覆盖查询,速度是最快的

2.若是覆盖索引指定的数据仅在辅助索引中能找到,则不须要再查找汇集索引数据就能找到:

# 好比
# 假设stu表的name字段是一个辅助索引
select name from stu where name = 'jack':

8.回表查询

1.指的是在当前索引结构中(辅助索引)找不到所需的数据,须要经过主键id去汇集索引中查询,速度慢于汇集索引

2.步骤:从辅助索引中获取主键的值,再拿着主键值到汇集索引中找到sex值

# 好比
# name字段是一个辅助索引,而sex字段不是索引
select sex from stu where name = 'jack';

9.查询速度对比

汇集索引 > 覆盖索引 > 非覆盖索引

6、正确使用索引

1.测试

# 建表
create table usr(id int,name char(10),gender char(3),email char(30));
#准备数据
delimiter //
create procedure addData(in num int)
begin 
declare i int default 0;
while  i < num do
    insert into usr values(i,"jack","m",concat("xxxx",i,"@qq.com"));    
set i  = i + 1;
end while;
end//
delimiter ;

#执行查询语句 观察查询时间
select count(*) from usr where id = 1;
#1 row in set (3.85 sec)
#时间在秒级别 比较慢


1.
#添加主键
alter table usr add primary key(id);
#再次查询
select count(*) from usr where id = 1;
#1 row in set (0.00 sec)
#基本在毫秒级就能完成 提高很是大

2.
#当条件为范围查询时
select count(*) from usr where id > 1;
#速度依然很慢 对于这种查询没有办法能够优化由于须要的数据就是那么多
#缩小查询范围 速度立马就快了
select count(*) from usr where id > 1 and id < 10;


#当查询语句中匹配字段没有索引时 效率测试
select count(*) from usr where name = "jack";
#1 row in set (2.85 sec)
# 速度慢


3.
# 为name字段添加索引
create index name_index on usr(name);
# 再次查询
select count(*) from usr where name = "jack";
#1 row in set (3.89 sec)
# 速度反而下降了 为何?
#因为name字段的区分度很是低 彻底没法区分 ,由于值都相同 这样一来B+树会没有任何的子节点,像一根竹竿每一都匹配至关于,有几条记录就有几回io ,全部要注意 区分度低的字段不该该创建索引,不能加速查询反而下降写入效率,
#同理 性别字段也不该该创建索引,email字段更加适合创建索引

# 修改查询语句为
select count(*) from usr where name = "aaaaaaaaa";
#1 row in set (0.00 sec) 速度很是快由于在 树根位置就已经判断出树中没有这个数据 所有跳过了

# 模糊匹配时
select count(*) from usr where name like "xxx"; #快
select count(*) from usr where name like "xxx%"; #快
select count(*) from usr where name like "%xxx"; #慢
#因为索引是比较大小 会从左边开始匹配 很明显全部字符都能匹配% 因此全都匹配了一遍


4.索引字段不能参加运算
select count(*) from usr where id * 12 = 120;
#速度很是慢缘由在于 mysql须要取出全部列的id 进行运算以后才能判断是否成立
#解决方案
select count(*) from usr where id = 120/12;
#速度提高了 由于在读取数据时 条件就必定固定了 至关于
select count(*) from usr where id = 10;
#速度天然快了

5.有多个匹配条件时 索引的执行顺序  and 和 or
#先看and
#先删除全部的索引
alter table usr  drop primary key;
drop index name_index on usr;

#测试
select count(*) from usr where name = "jack" and gender = "m" and id = 1 and email = "xxxx2@qq.com";
#1 row in set (1.34 sec) 时间在秒级 

#为name字段添加索引
create index name_index on usr(name);
#测试
select count(*) from usr where name = "jack" and gender = "m" and id = 1 and email = "xxxx2@qq.com";
#1 row in set (17.82 sec) 反而时间更长了

#为gender字段添加索引
create index gender_index on usr(gender);
#测试
select count(*) from usr where name = "jack" and gender = "m" and id = 1 and email = "xxxx2@qq.com";
#1 row in set (16.83 sec) gender字段任然不具有区分度 

#为id加上索引
alter table usr add primary key(id);
#测试
select count(*) from usr where name = "jack" and gender = "m" and id = 1 and email = "xxxx1@qq.com";
#1 row in set (0.00 sec) id字段区分度高 速度提高
#虽然三个字段都有索引 mysql并非从左往右傻傻的去查 而是找出一个区分度高的字段优先匹配

#改成范围匹配
select count(*) from usr where name = "jack" and gender = "m" and id > 1 and email = "xxxx1@qq.com";
#速度变慢了

#删除id索引 为email创建索引
alter table usr drop primary key;
create index email_index on usr(email);
#测试
select count(*) from usr where name = "jack" and gender = "m" and id = 1 and email = "xxxx2@qq.com";
#1 row in set (0.00 sec) 速度很是快

#对于or条件 都是从左往右匹配 
select count(*) from usr where name = "jackxxxx" or email = "xxxx0@qq.com";

#注意 必须or两边都有索引才会使用索引 

and 语句中只要有一个存在索引就能提升速度  


6.多字段联合索引
为何须要联合索引
案例:
select count(*) from usr where name = "jack" and gender = "m" and id  > 3 and email = "xxxx2@qq.com";
假设全部字段都是区分度很是高的字段,那么除了id为谁添加索引都可以提高速度,可是若是sql语句中没有出现索引字段,那就没法加速查询,最简单的办法是为每一个字段都加上索引,可是索引也是一种数据,会占用内存空间,而且下降写入效率
此处就可使用联合索引,

联合索引最重要的是顺序 按照最左匹配原则 应该将区分度高的放在左边 区分度低的放到右边
#删除其余索引
drop index name_index on usr;
drop index email_index on usr;
#联合索引
create index mul_index on usr(email,name,gender,id);
create index mul_index on usr(id,email,gender,name);  # 推荐
# 查询测试
select count(*) from usr where name = "xx" and id = 1 and email = "xx";
只要语句中出现了最左侧的索引(email) 不管在前在后都能提高效率 

drop index mul_index on usr;

2.结论:

1.使用占用空间最小的字段做为索引

2.不要在一行中存储太多的数据,例如小说、视频,若是字段太多能够分表

3.尽可能使用覆盖查询

4.若是字段区分度低(字段重复度高),创建索引是没有意义的,反过来讲应该将区分度高的字段(好比自增的id)做为索引

5.模糊匹配中,百分号尽可能不要写在前面

**6.不要在等号的左边作运算,例如:select count(*) from usr where id*3 = 6 -- 也会遍历全部记录 ;**

7.and语句中会自动找一个具有索引的字段优先执行,因此咱们应该在and语句中至少包含一个具有索引的字段

8.or语句要避免使用,若是要用,则要保证全部字段都有索引才能加速

9.联合索引中,顺序应该将区分度最高的放到左边,最低的放到右边,查询语句中必须保证最左边的索引出如今语句中

3.须要注意的是:

1.若是要查询的数据量很是大时,索引将没法加速

2.不是添加了索引就能提速,须要考虑索引添加的是否合理,SQL语句是否使用到了索引

7、语法

1.建立索引的语法:

create index 索引的名字 on 表名称(字段名);

2.删除索引:

drop index 索引名称 on 表名;

3.联合索引:

create index 索引名称 on 表名(字段名1,字段名2,......)
相关文章
相关标签/搜索