MySQL索引

MySQL索引

1. 索引存在的意义

MySQL 对数据的查询本质上就是与磁盘进行 IO 交换,当一个数据库的记录数量非常庞大时,MySQL 可能就需要进行大量的 IO 才能找到对应的数据,IO 对性能的消耗十分庞大,如果没有索引,MySQL 在查询数据时就需要大量时间检索才能返回结果,甚至在查询的过程中就挂掉了。

2. 索引与磁盘的交互

索引本质上就是一种数据结构,使数据通过某种有序的结构管理起来,当 MySQL 需要查询一个数据时,就会根据索引构建的有序关系,快速的找到这个数据在磁盘中的位置,减少 IO 消耗。

我们都知道,CPU 访问内存的速度要远快于访问磁盘的速度,MySQL 提高检索速度的策略是:利用索引构建数据的有序关系后,还要占用高内存来提升数据的访问速度。 系统与磁盘交互的基本单位是块,每块 4   K B 4\space \rm{KB} 4 KB 大小,而 MySQL 的内存,如 InnoDB 与磁盘进行 IO 的大小是 16   K B 16\space \rm{KB} 16 KB

mysql> SHOW GLOBAL STATUS LIKE 'innodb_page_size';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| Innodb_page_size | 16384 |
+------------------+-------+
1 row in set (0.01 sec)

即当 MySQL 需要到磁盘中检索数据时,一次会带上 16   K B 16\space \rm{KB} 16 KB 大小的数据到 MySQL 的**内存池(buffer pool)**中,接下来如果需要访问的数据在这 16   K B 16\space \rm{KB} 16 KB 中,就能快速地返回结果。

MySQL 与磁盘交互也是通过系统的,系统与磁盘交互的基本单位是 4   K B 4\space \rm{KB} 4 KB ,那么实践执行 MySQL 的交互就需要系统进行 4 次磁盘交互,才能将 16   K B 16\space \rm{KB} 16 KB 的数据加载到内存中(但可能也会有优化)。

3. 索引是一种数据结构

索引本质上就是一种数据结构,其中 InnoDBMyISAM 使用 B+ 树实现MEMORY 默认使用哈希索引,这里主要介绍最常见的 InnoDB 索引。

B+ 树的特点是叶子节点存储有效数据,而其他节点都是其子节点的索引。形象地说,叶子节点就相当于一本书的内容,而叶子节点的父结点就是这本书的目录,父结点的父结点就是目录的目录。B+ 树的优点就在于,即使存储的数据量庞大,但树的高度很低。且叶子节点兄弟之间存在指向,顺序访问方便,对数据库来说是一种十分合适的数据结构。

3.1 page

InnoDB 对 B+ 树进行了一点小小的改造:不只是叶子节点相连,非叶子节点之间也会相连InnoDB 使非叶子节点作为目录节点,目录节点内存在多个索引,指向不同的叶子节点。目录节点的兄弟节点之间连接,当检索一个数据时,在第一个目录节点没有找到,也能迅速跳转到它的兄弟节点进行检索,一定程度上提高了检索速度。

InnoDB 中每个 page 就是一个节点,占 16   K B 16\space \rm{KB} 16 KB 大小。一个叶子节点包含了 16   K B 16\space \rm{KB} 16 KB 的数据,一个目录节点包含了 16   K B 16\space \rm{KB} 16 KB 的子节点索引,当目录节点也不够存时,就会增加一个目录节点的目录节点,占 16   K B 16\space \rm{KB} 16 KB 大小。

MySQL索引_第1张图片

3.2 聚簇索引和非聚簇索引

聚簇索引就是上图展示,InnoDB 使用的 B+ 树,叶子节点既包含了内部目录又包含了数据的结构。而 MyISAM 使用的数据结构也是 B+ 树,但它使用的是非聚簇索引,即叶子节点只有额外的指针存储对应数据的地址MyISAM 最大的特点是将索引 page 与数据 page 分离开来

MySQL索引_第2张图片

但聚簇索引和非聚簇索引是相对于主键索引来说的,如果用户创建了第二个辅助索引,InnoDBMyISAM 都会使用非聚簇索引来存储这种索引结构,以此来节省空间。

3.3 总结

索引本质上就是一种数据结构,是一种用空间换时间的策略,每个索引都会创建一个新的数据结构来构建索引关系。

4. 索引的种类

4.1 主键索引(primary key)

一个表中,只能有一个主键索引,主键索引的效率很高(因为主键不能重复),创建主键的列值不能为 NULL ,一般我们会在 int 类型上使用主键。

使用方法:

-- 1.在字段后面指定primary key
create table  tb_name(id int primary key, name varchar(10));

-- 2.在创建表的最后,指定哪个字段为primary key
create table  tb_name(id int, name varchar(10), primary key(id)); 

-- 3.在创建表之后再添加主键
create table  tb_name(id int, name varchar(10));
alter table tb_name add primary key(id);

4.2 唯一索引(unique)

一个表中可以有多个唯一索引,唯一索引的查询效率高,使用唯一索引的列不允许有相同的值,但允许为 NULL (如果指定该字段为 NOT NULL 效果等价于主键索引)。

使用方法:

-- 1.在表定义时,在某列后直接指定unique唯一属性
create table user4(id int primary key, name varchar(30) unique);

-- 2.创建表时,在表的后面指定某列或某几列为unique
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);

4.3 普通索引(index)

一个表中可以有多个普通索引,使用普通索引的列允许有多个相同的值,在实际开发中,我们也只在需要创建索引、且该列有重复的值时使用。

使用方法:

 -- 1.在表的定义最后,指定某列为index索引
create table user8(id int primary key,name varchar(10),index(name));

-- 2.创建完表以后指定某列为index索引
create table user9(id int primary key,  name varchar(20), alter table user9 add index(name); 
 
-- 3.创建一个索引名为idx_name的索引    
create table user10(id int primary key,  name varchar(20))
create index idx_name on user10(name);

4.4 全文索引(fulltext)

当字段存储的内容是大量的文字,就需要全文索引来对字段中的内容进行索引。但 MySQL 要求使用全文索引的表的存储引擎必须是 MyISAM,且默认的全文索引支持英文,不支持中文。如果对中文进行全文检索,可以使用 sphinx 的中文版 coreseek。

使用方法:

CREATE TABLE articles (
 id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
 title VARCHAR(200),
 body TEXT,
 FULLTEXT (title,body)
 )engine=MyISAM;

5. 其他

5.1 查询索引的方法

show keys from tb_name;

show index from tb_name;

5.2 删除索引的方法

删除主键索引:

alter table tb_name drop primary key;

删除其他索引:

alter table tb_name drop index 索引名;

注意索引名是使用索引的字段。

或者使用

drop index 索引名 on tb_name;

你可能感兴趣的:(mysql,adb,数据库)