mysql索引原理与慢查询优化
一:什么是索引
01:索引的出现是为了提高查询数据的效率02:索引在mysql叫做“键” 或则“key“(primary key,uniquekey ,还有一个index key),是存储引擎用于快速找到记录的一种数据结构。索引能减少io次数,加速查询(primary key 和unique key ,除了有加速查询的效果外,还有约束的效果,primary key 不为空且唯一,unique key唯一,而index key 只有加速查询的效果,没有约束效果)03:优缺点:索引太多,应用程序的性能会受到影响,索引太少,对查询性能又会产生影响,需要找到一个平衡点。应该在一开始在需要的地方添加索引。04:索引的原理:索引时在没有数据的时候先建立索引然后再往里面添加数据,这样数据在查找的时候就能不断缩小需要查找的数据的范围了,索引就像是书的目录。在不断添加数据后,索引的能增加查询效率。但是会降低写入效率(一旦有新的数据块写入,原来的索引就没用了。需要重新建立索引。)索引的影响:01:在表中有大量的数据的前提下,创建索引速度会很慢02: 在创建索引后,对表的查询速度会大幅度提升,但是写性能会降低。索引的本质:通过不断缩小想要的数据的范围来筛选出最终想要的结果,同时把随机事件变成顺序时间,也就是说,有了索引机制,可以总是用同一种查找方式来锁定数据。
二:磁盘I/O与预读
磁盘读取数据是靠机械运动,每次读取数据花费的时间由寻道时间(磁臂移动到磁道所用的时间),旋转时间(磁盘转速)和 传输时间(将数据从磁盘读取或则写入)三个部分。每次访问磁盘需要花费很多时间(相对于cpu处理数据的速度)。所以考虑到io操作每次读取数据占用的时间大小,计算机操作系统做了优化,当一次io操作的时候,不光把当前磁盘地址的数据,还把相邻的数据也都读取到内存缓冲区内。因为局部预读性原理告诉我们,当计算机访问一个地址的数据的时候,与其相邻的数据也会很快被访问到。每一次IO读取的数据我们称之为一页(page)。具体一页有多大数据跟操作系统有关,一般为4k或8k,也就是我们读取一页内的数据时候,实际上才发生了一次IO,这个理论对于索引的数据结构设计非常有帮助。
三:索引的数据结构
说明:b+数主要是为了磁盘读取查找数据出现的。(树形演示)索引的结构就是为了减少io,加速查询。索引的数据结构是 ”b+树(B+树是通过二叉查找树,再由平衡二叉树,b数演化而来。)”
01:b+树查找过程
02:b+树的性质:
01:索引字段要尽量的小io次数主要取决于b+数的高度,高度越低,io查询的次数就越少。02:索引的最匹配特性就是要查找的数据,先从数据块的最左边开始查询,再匹配右边的
四:聚集索引和辅助索引
01:聚集索引 说的就是mysql的数据的主键。innodb存储引擎的表必须要有一个主键。
myisam存储引擎在创建表的时候会生成三个文件:
.frm (存储表的结构).myd(是数据文件).myi(索引文件)
innodb存储引擎创建表的时候会生成两个文件
.frm(存储结构).idb(存储数据和索引)
创建innodb存储引擎的表时,就需要给表一个主键,那么innodb引擎在存储数据的时候就默认按照索引的树形结构来保存。这种索引就是聚集索引。这样做主要是为了加快查询速度。
02:在数据库中,B+树的高度一般是2--4层,也就是说查找一个键值的行记录最多只需要2到4次io,因为当前的机械硬盘至少可以做100次io
2--4次的io意味着查询的时间只需要0.02---0.04秒
数据库中的B+树索引可以分为聚集索引和辅助索引聚集索引和辅助索引相同的是:两者内部都是b+数的形式,高度是平衡的,叶子结点存放着所有的数据聚集索引和辅助索引的不同点是:叶子结点是否存放的是一整行的信息。
03:聚集索引
优点:01:对主键的排序查找和范围查找速度非常快,叶子结点的数据就是用户需要的数据。02: 范围查询 : 如果需要查找主键某一范围的数据,通过叶子结点的上层中间结点就可以得到页的范围,之后直接读取数据页即可
04:辅助索引:
表中除了聚集索引外其他索引都是辅助索引(Secondary Index,也称为非聚集索引)(unique key啊、index key啊),与聚集索引的区别是:辅助索引的叶子节点不包含行记录的全部数据
五:mysql索引管理
01:索引的功能是快速查找02:mysql中德primary key unique,联合唯一都是索引,这些索引除了加速查找以外还有约束功能03:常用的索引001:普通索引index: 加速查找002:唯一索引:主键索引 primary key :加速查找和约束unique(id,name) :联合唯一索引index(id,name):联合普通索引04:建立索引删除索引创建索引三种方法:001:alter table 表名 add primary key(需要加索引的字段) (eg: alter table t1 add primary key(id) 给t1表的id加索引)002:create index 索引名 on 表名(字段名)(eg: create index ix_id on t1(id) 给t1表的id加索引)003:创建表时给其加索引create table 表名(字段名1 数据类型 完整约束条件字段名2 数据类型 完整约束条件索引名 字段名3(长度));例子:create table t1(id int,name char,age int,sex enum("male","female"),unique key uni_id(id),index ix_name(name) #index 没有key
);删除索引:drop index 索引名字 on 表名字
六:测试索引
1:准备表
create table s1(id int,name varcahr(20),gender cahr(6),email varchar(50));
2:创建存储过程,实现批量插入数据
delimiter //create procedure auto_insert()begindecalare i in default 1;while (i<3000000) doinsert into s1 values(i,"TOM","male",concat("TOM",i,"oneboy"));set i&#61;i&#43;1;end while;end //delimiter ;
3:查看存储过程
show create procedure auto_insert\G
4:调用存储过程
call auto_insert();
总结&#xff1a;#1. 一定是为搜索条件的字段创建索引&#xff0c;比如select * from s1 where id &#61; 333;就需要为id加上索引#2. 在表中已经有大量数据的情况下&#xff0c;建索引会很慢&#xff0c;且占用硬盘空间&#xff0c;建完后查询速度加快
比如create index idx on s1(id);会扫描表中所有的数据&#xff0c;然后以id为数据项&#xff0c;创建索引结构&#xff0c;存放于硬盘的表中。建完以后&#xff0c;再查询就会很快了。#3. 需要注意的是&#xff1a;innodb表的索引会存放于s1.ibd文件中&#xff0c;而myisam表的索引则会有单独的索引文件table1.MYI
MySAM索引文件和数据文件是分离的&#xff0c;索引文件仅保存数据记录的地址。而在innodb中&#xff0c;表数据文件本身就是按照B&#43;Tree&#xff08;BTree即Balance True&#xff09;组织的一个索引结构&#xff0c;这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键&#xff0c;因此innodb表数据文件本身就是主索引。因为inndob的数据文件要按照主键聚集&#xff0c;所以innodb要求表必须要有主键&#xff08;Myisam可以没有&#xff09;&#xff0c;如果没有显式定义&#xff0c;则mysql系统会自动选择一个可以唯一标识数据记录的列作为主键&#xff0c;如果不存在这种列&#xff0c;则mysql会自动为innodb表生成一个隐含字段作为主键&#xff0c;这字段的长度为6个字节&#xff0c;类型为长整型.