【MySQL】索引

数据库文件的存储

MySQL给用户提供存储服务,存储的数据在磁盘中。

找到一个文件的全部,本质就是在磁盘中找到所有保存这个文件的扇区。
系统读取磁盘是以块为单位的,基本单位为4KB.

MySQL作为一款应用软件可被认为成一种特殊的文件系统,它有更高的IO场景。为提高效率,MySQL进行IO的基本单位是16KB,叫做MySQL的page.

注意

1.MySQL中的数据文件是以page为单位保存在磁盘中的。

2.MySQL的CURD操作要通过计算找到要修改的位置。

3.计算需要CPU参与,所以要将数据先加载到内存中。所以在特定的时间内,数据一定是磁盘和内存中都有。操作完内存数据后以特定的刷新策略刷新到磁盘,这时是磁盘和内存的数据交互(IO),基本单位为page。

4.MySQL服务器在内存中运行时,在服务器内部申请了叫做Buffer Poll的大内存空间来进行各种缓存。

5.提高算法效率的因素:a.组织数据的方式 b.算法本身

索引的理解

建立测试表:

插入一些数据:

发现默认是有序的。是mysqld自己做的,为了很方便的引入目录。

注意,在MySQL服务器内部的缓冲区中,MySQL要将多个同时存在的page用链表管理起来。

数据库在插入数据时要对其进行排序是因为要优化查询的效率。页内部存放数据的模块实质上也是一个链表的结构,链表的特点是增删快,查改慢,所以优化查询效率很重要。有序后在查找时从头到尾都是有效查找。

引入目录

随着数据量的增大,MySQL中必定会有多个页来存储数据,然后通过指针的方式将所有的page组织起来。

用上述图中的方法仍然需要大量的IO,将下一个page加载到内存进行线性检测,显得之前的目录杯水车薪。

解决方案:

给page也带上目录:

1.使用一个目录项来指向某一页,而这个目录项存放的是将要指向的页中存放的最小数据的键值。

2.和页内目录不同的地方在于这种目录管理的级别是页,而页内目录管理级别是行。

3.每个目录的构成都是键值+指针。

目录页的本质也是页,普通页中存的数据是用户数据,而目录页中存的数据是普通页的地址。

以后我们检索数据时自顶向下来遍历 。

最终目录和数据成了一棵B+树,我们已经给表user完成了主键索引。

为什么InnoDB不用B树作为底层索引?

对我们来说的最大区别:

1.B树结点既有数据又有page指针,而B+只有叶子结点有数据,其他目录页只有键值和page指针。

2.B+叶子结点全部相连,而B没有。

所以:

1.结点不存储数据就可以存更多的目录,使得树更矮,所以IO操作次数更少。

2.叶子结点相连便于进行范围查找。

聚簇索引 VS 非聚簇索引

MyISAM存储引擎--主键索引

MyISAM同样使用B+树作为索引结果,叶子结点的data域存放的是数据记录的地址。

下图为 MyISAM 表的主索引,其中Col1 为主键。

MyISAM 最大的特点是将索引Page和数据Page分离,也就是叶子节点没有数据,只有对应数据的地址
而InnoDB 是将索引和数据放在一起的。

MyISAM这种用户数据与索引数据分离的索引方案,叫做非聚簇索引。

InnoDB 这种用户数据与索引数据在一起索引方案,叫做聚簇索引。

MySQL除了默认会建立主键索引外,用户也可能按照其他列信息建立索引,这种索引叫做辅助(普通)索引。

对于 MyISAM ,建立辅助(普通)索引和主键索引没有差别 ,无非就是主键不能重复,而非主键可重复。

下图就是基于 MyISAM 的 Col2 建立的索引,和主键索引无差别:

InnoDB 除了主键索引,用户也会建立辅助(普通)索引,我们以上表中的 Col3 建立对应的辅助索引如下

图:

InnoDB 的非主键索引中叶子节点并没有数据,而只有对应记录的key值。所以InnoDB 通过辅助(普通)索引,找到目标记录需要两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。这种过程,叫做回表查询

索引操作

创建主键索引

法一:

sql 复制代码
create table user1(id int primary key, name varchar(30));

法二:

sql 复制代码
create table user2(id int, name varchar(30), primary key(id));

法三:

sql 复制代码
create table user3(id int, name varchar(30)); 
-- 创建表以后再添加主键 
alter table user3 add primary key(id); 

主键索引的特点:

1.一个表中最多一个主键索引。

2.效率高。

3.创建主键索引的列,它的值不能是null且不能重复。

4.主键索引的列基本上是int.
唯一索引的创建

法一:

sql 复制代码
create table user4(id int primary key, name varchar(30) unique); 

法二:

sql 复制代码
create table user5(id int primary key, name varchar(30), unique(name));

法三:

sql 复制代码
create table user6(id int primary key, name varchar(30)); 
alter table user6 add unique(name); 

唯一索引的特点:

1.一个表中,可以有多个唯一索引

2.查询效率高

3.如果在某一列建立唯一索引,必须保证这列不能有重复数据

4.如果一个唯一索引上指定not null,等价于主键索引。
普通索引的创建

法一:

sql 复制代码
create table user8(id int primary key, 
 name varchar(20), 
 email varchar(30), 
 index(name) --在表的定义最后,指定某列为索引 
); 

法二:

sql 复制代码
create table user9(id int primary key, name varchar(20), email varchar(30)); 
alter table user9 add index(name); --创建完表以后指定某列为普通索引 

法三:

sql 复制代码
create table user10(id int primary key, name varchar(20), email varchar(30)); 
-- 创建一个索引名为 idx_name 的索引 
create index idx_name on user10(name);

普通索引的特点:

1.一个表中可以有多个普通索引,普通索引在实际开发中用的比较多。

2.如果某列需要创建索引,但是该列有重复的值,那么我们就应该使用普通索引。
查询索引

法一:

sql 复制代码
show keys from 表名

法二:

sql 复制代码
show index from 表名;

法三:

sql 复制代码
desc 表名;

删除索引

1.删除主键索引

sql 复制代码
alter table 表名 drop primary key; 

2.删除其他索引

sql 复制代码
alter table 表名 drop index 索引名;

索引名就是show keys from 表名中的Key_name 字段.

sql 复制代码
drop index 索引名 on 表名;

索引创建原则

1.频繁作为查询条件的字段应该创建索引。

2.唯一性太差的字段不适合单独创建索引(即使频繁作为查询条件)

3.更新非常频繁的字段不适合创建索引。

4.不会出现在where子句中的字段不该创建索引。
全文索引的创建

当对有大量文字的字段进行检索时,会使用到全文索引。MySQL提供全文索引机制,但要求表的存储引擎必须是MyISAM,且默认的全文索引支持英文,不支持中文。

查询有没有database数据

如果使用如下查询方式,虽然查询出数据,但是没有使用到全文索引:

key为null表示没有用到索引。

如何使用全文索引?

相关推荐
InfinteJustice2 小时前
mysql如何设计积分系统_mysql流水账与余额对账
jvm·数据库·python
NotFound4862 小时前
Golang怎么实现防重复提交_Golang如何用Token机制防止表单重复提交【技巧】
jvm·数据库·python
T0uken2 小时前
【Linux】耗时任务执行并邮件通知
linux·运维·服务器
c++逐梦人2 小时前
Linux生产者消费者模型
linux
2401_865439632 小时前
CSS如何实现图片自动裁剪填充_巧用object-fit属性控制尺寸
jvm·数据库·python
m0_748839492 小时前
HTML函数能否用液态金属散热提升性能_极端散热方案实测【汇总】
jvm·数据库·python
2301_803538952 小时前
mysql添加索引导致插入变慢怎么办_索引优化与异步处理方案
jvm·数据库·python
2301_782659182 小时前
如何防止SQL脏数据写入_利用触发器实现强一致性校验
jvm·数据库·python
2301_817672263 小时前
如何实现元素从底部进入视口时触发 sticky 定位
jvm·数据库·python