数据库中的索引

一、索引的好处

首先,我们先看一个例子。

再上图中我们有一个8000000数据的表叫EMP,一开始我们没有主键查找一个值花了4.07秒,若加上了主键花的时间小于0.01秒,所以在大量数据中查找有没有索引就尤为重要。

索引:提高数据库的性能,索引是物美价廉的东西了。不用加内存,不用改程序,不用调sql,只要执行正确的 create index ,查询速度就可能提高成百上千倍。但是天下没有免费的午餐,查询速度的提高是以插入、更新、删 除的速度为代价的,这些写操作,增加了大量的IO。所以它的价值,在于提高一个海量数据的检索速度。

二、认识磁盘

在磁盘中找数据:磁头(head,决定数据在哪一面)-> 磁道(track)柱面(cylinder)(决定在面上的哪个同心圈)-> 扇区(sector,决定在哪个区)

上述在硬件中查找数据方式:CHS

在操作系统中查找方式:LBA 虚拟地址->物理地址

系统读磁盘以块为单位,基本单位4KB

随机访问:本次IO的扇区地址与上次IO地址不连续,这样磁头两次IO之间要有较大的移动才能读写数据。

连续访问:本次IO的扇区地址与上次IO地址连续。

当然操作系统会对地址进行排序,尽量以连续方式进行IO

三、MySQL与磁盘交互的基本单位

上图中InnoDB中的page大小就是16KB

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

MySQL 的 CURD 操作,都需要通过计算,找到对应的插入位置,或者找到对应要修改或者查询的数据。 而只要涉及计算,就需要CPU参与,而为了便于CPU参与,一定要能够先将数据移动到内存当中。

所以在特定时间内,数据一定是磁盘中有,内存中也有。后续操作完内存数据之后,以特定的刷新策略,刷新 到磁盘。而这时,就涉及到磁盘和内存的数据交互,也就是IO了。

而此时IO的基本单位就是Page。 为了更好的进行上面的操作, MySQL 服务器在内存中运行的时候,在服务器内部,就申请了被称为 Buffer Pool 的的大内存空间,来进行各种缓存。其实就是很大的内存空间,来和磁盘数据进行IO交互。 为了更高的效率,一定要尽可能的减少系统和磁盘IO的次数。

四、page在MySQL中的理解

1、建模

上面我们提到MySQL中有大量数据存放在page中,所以MySQL中有大量的page,要把他们管理起来就要先描述再组织,在Buffer Pool中建模。

struct page

{

struct page* prev;

struct page* next;

char buff[NUM];

}

2、为什么要用page进行IO交互

预加载机制有效利用局部性原理提高IO效率。

预加载机制:单个page大小16KB,可以加载大量数据。

局部性原理:加载周边数据,预测用户下次查找地址,减少IO次数,提高效率。

五、InnoDB中的索引结构

但是上述的page组织结构存在很大问题,由于是链表形式链接一个个page,导致查询结果是O(N),是绝对不能接受的,所以引入页目录。然而我们知道数据的组织形式是page内部存有数据,page外部再用数据结构连接,所以要想提高效率就要从这两方面入手。

1、理解单个page

由于单个page中有大量数据,那么我们在其中设置目录就能范围查找,加快速度。

所以我们理解了为什么无序插入带有主键的表,出来的主键是有序的,那是因为只有有序才能在目录查找时是有意义的。

2、多页情况

这就像是B+树的结构,非叶子节点不存数据,存放叶子节点的索引,只有在最后一层才存放完整数据,并且用链表链接(上图是错的,非叶子节点是没有链表把page链接在一起的)

细节

(1)非叶子节点不存数据,可以储存更多的目录,管理更多的page

(2)查找时只要加载部分目录到内存即可完成查找,减少IO次数。

六、InnoDB与MyISAM引擎

MyISAM最大的特点就是索引page和数据page分离,叶子结点只有数据地址,是非聚簇索引。

而InnoDB是将数据和索引放一起模式聚簇索引。

值得一提的是在InnoDB中创建辅助索引,叶子结点并没有数据,只有主键值,然后用主键值在主键索引树中查到数据,叫做回表查询。

那为什么不放数据呢?没必要存多份数据,太浪费空间。

具体介绍可查看我的文章http://t.csdnimg.cn/D53Du

截图以供参考

七、索引操作

1、创建主键索引

(1)create table user1(id int primary key, name varchar(30));

(2)create table user2(id int, name varchar(30), primary key(id));

(3)create table user3(id int, name varchar(30));

alter table user3 add primary key(id);

主键索引的特点

(1) 一个表中,最多有一个主键索引,当然可以使复合主键 主键索引的效率高(主键不可重复) (2)它的值不能为null,且不能重复。

(3)主键索引的列基本上是int

2、创建唯一索引

(1) create table user4(id int primary key, name varchar(30) unique);

(2)create table user5(id int primary key, name varchar(30), unique(name));

(3)create table user6(id int primary key, name varchar(30));

alter table user6 add unique(name);

唯一索引的特点

(1)一个表中,可以有多个唯一索引 查询效率高。

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

(3)如果一个唯一索引上指定not null,等价于主键索引。

3、创建普通索引

(1)create table user8(id int primary key, name varchar(20), email varchar(30), index(name));

(2)create table user9(id int primary key, name varchar(20), email varchar(30));

alter table user9 add index(name);

(3)create table user10(id int primary key, name varchar(20), email varchar(30));

create index idx_name on user10(name);创建一个索引名为 idx_name 的索引

普通索引的特点

(1)一个表中可以有多个普通索引。

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

4、删除索引

(1)删除主键索引

alter table 表名 drop primary key;

(2)删除其他索引

alter table 表名 drop index 索引名; 索引名就是show keys from 表名中的 Key_name 字段

drop index 索引名 on 表名 ;

5、查询索引

(1)show keys from 表名;

(2)show index from 表名;

(3)desc 表名;

6、全文索引

explain sql语句; 用来解释要怎么执行sql语句

举例

上图是创建了一个文本。

当我们用传统的where子句查询时发现key:NULL,说明没有用到索引查询,效率必然低。

语法

select * from 表名 where match (全文索引名) against ('关键字');

这时key:title就表示用title充当全文索引来查找关键字'database'

7、复合索引

语法

alter table 表名 add index (索引名1,索引名2....)

会以索引名1来创建B+树

上图我们就把name和email当做复合索引

我们知道用普通索引找一个值会找2次,但是用复合索引,并且索引绑定了我们要查找的值,我们就可以只找一次。

例如,index(name, email)后,我们要找张三的邮箱,只要name找到张三就行,返回绑定的邮箱数据,而这种未通过主键找到email的行为就是索引覆盖,覆盖的是主键。

在上述例子中,我们可以拿"张三"或"张三+邮箱"来查找数据,但是不能只拿"邮箱"查找数据,这就是索引的最左匹配原则。

相关推荐
科技小花2 小时前
数据治理平台架构演进观察:AI原生设计如何重构企业数据管理范式
数据库·重构·架构·数据治理·ai-native·ai原生
一江寒逸2 小时前
零基础从入门到精通MySQL(中篇):进阶篇——吃透多表查询、事务核心与高级特性,搞定复杂业务SQL
数据库·sql·mysql
D4c-lovetrain2 小时前
linux个人心得22 (mysql)
数据库·mysql
阿里小阿希2 小时前
CentOS7 PostgreSQL 9.2 升级到 15 完整教程
数据库·postgresql
荒川之神3 小时前
Oracle 数据仓库雪花模型设计(完整实战方案)
数据库·数据仓库·oracle
做个文艺程序员3 小时前
MySQL安全加固十大硬核操作
数据库·mysql·安全
不吃香菜学java3 小时前
Redis简单应用
数据库·spring boot·tomcat·maven
一个天蝎座 白勺 程序猿3 小时前
Apache IoTDB(15):IoTDB查询写回(INTO子句)深度解析——从语法到实战的ETL全链路指南
数据库·apache·etl·iotdb
不知名的老吴3 小时前
Redis的延迟瓶颈:TCP栈开销无法避免
数据库·redis·缓存
YOU OU3 小时前
三大范式和E-R图
数据库