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存储引擎创建表的时候会生成两个文件
创建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()
begin
decalare i in default 1;
while (i<3000000) do
insert into s1 values(i,"TOM","male",concat("TOM",i,"oneboy"));
set i=i+1;
end while;
end //
delimiter ;
3:查看存储过程
show create procedure auto_insertG
4:调用存储过程
总结:
#1. 一定是为搜索条件的字段创建索引,比如select * from s1 where id = 333;就需要为id加上索引
#2. 在表中已经有大量数据的情况下,建索引会很慢,且占用硬盘空间,建完后查询速度加快
比如create index idx on s1(id);会扫描表中所有的数据,然后以id为数据项,创建索引结构,存放于硬盘的表中。
建完以后,再查询就会很快了。
#3. 需要注意的是:innodb表的索引会存放于s1.ibd文件中,而myisam表的索引则会有单独的索引文件table1.MYI
MySAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。而在innodb中,表数据文件本身就是按照B+Tree(BTree即Balance True)
组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此innodb表数据文件本身就是主索引。
因为inndob的数据文件要按照主键聚集,所以innodb要求表必须要有主键(Myisam可以没有),如果没有显式定义,则mysql系统会自动选择一个
可以唯一标识数据记录的列作为主键,如果不存在这种列,则mysql会自动为innodb表生成一个隐含字段作为主键,这字段的长度为6个字节,
类型为长整型.