MySQL 索引

  • ​​前言​​
  • ​​一、什么是索引​​
  • ​​二、索引的创建​​
  • ​​1、通过创建表创建索引​​
  • ​​2、已经存在的表创建索引​​
  • ​​三、索引 案例实战​​

前言

本环境是基于 Centos 7.8 系统构建MySQL-5.7.14
具体构建,请参考 ​​MySQL-5.7.14 环境构建​​

索引是一种特殊的数据库结构,可以用来快速查询数据库表中的特定记录。索引是提高数据库性能的重要方式。MySQL中,所有的数据类型都可以被索引。MySQL的索引包括普通索引、惟一性索引、全文索引、单列索引、多列索引和空间索引等。接下来,我将详细介绍MySQL的索引。


一、什么是索引

认识索引

模式(schema)中的一个数据库对象

  • 在数据库中用来加速对表的查询
  • 通过使用快速路径访问方法快速定位数据,减少了磁盘的I/O
  • 与表独立存放,但不能独立存在,必须属于某个表
  • 由数据库自动维护,表被删除时,该表上的索引自动被删除。
  • 索引的作用类似于书的目录,几乎没有一本书没有目录,因此几乎没有一张表没有索引。

索引的优缺点

创建索引的最主要的原因:

  • 索引的优点是可以提高检索数据的速度
  • 对于有依赖关系的子表和父表之间的联合查询时,可以提高查询速度
  • 使用分组和排序子句进行数据查询时,同样可以显著节省查询中分组和排序的时间。

索引的缺点:

  • 创建和维护索引需要耗费时间,耗费时间的数量随着数据量的增加而增加
  • 索引需要占用物理空间,每一个索引要占一定的物理空间
  • 增加、删除和修改数据时,要动态的维护索引,造成数据的维护速度降低了。

MySQL的索引包括普通索引、惟一性索引、全文索引、单列索引、多列索引和空间索引。

二、索引的创建

开始之前,先说一下全文索引的版本、存储引擎、数据类型的支持情况

  • MySQL 5.6 以前的版本,只有 MyISAM 存储引擎支持全文索引;
  • MySQL 5.6 及以后的版本,MyISAM 和 InnoDB 存储引擎均支持全文索引;
  • 只有字段的数据类型为 char、varchar、text 及其系列才可以建全文索引。

1、通过创建表创建索引

# 创建普通索引
mysql> create table stu_name_index1
-> (id int,
-> name varchar(20),
-> gender enum('男','女') default '男',
-> index name_index(name));
Query OK, 0 rows affected (0.00 sec)

mysql> show create table stu_name_index1\G
*************************** 1. row ***************************
Table: stu_name_index1
Create Table: CREATE TABLE `stu_name_index1` (
`id` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`gender` enum('男','女') DEFAULT '男',
KEY `name_index` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

# 创建唯一索引
mysql> create table stu_id_index2
-> (id int primary key auto_increment,
-> name varchar(20),
-> gender enum('男','女') default '男',
-> unique index id_index(id desc));
Query OK, 0 rows affected (0.00 sec)

mysql> show create table stu_id_index2\G
*************************** 1. row ***************************
Table: stu_id_index2
Create Table: CREATE TABLE `stu_id_index2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`gender` enum('男','女') DEFAULT '男',
PRIMARY KEY (`id`),
UNIQUE KEY `id_index` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

# 创建全文索引
mysql> create table stu_id_index3
-> (id int,
-> name varchar(20),
-> gender enum('男','女') default '男',
-> fulltext index name_full_index(name));
Query OK, 0 rows affected (0.02 sec)

mysql> show create table stu_id_index3\G
*************************** 1. row ***************************
Table: stu_id_index3
Create Table: CREATE TABLE `stu_id_index3` (
`id` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`gender` enum('男','女') DEFAULT '男',
FULLTEXT KEY `name_full_index` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)



# 创建多列索引
```sql
mysql> create table stu_id_index4
-> (id int,
-> name varchar(20),
-> gender enum('男','女') default '男',
-> index more_index(id,name,gender));
Query OK, 0 rows affected (0.01 sec)

mysql> show create table stu_id_index4\G
*************************** 1. row ***************************
Table: stu_id_index4
Create Table: CREATE TABLE `stu_id_index4` (
`id` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`gender` enum('男','女') DEFAULT '男',
KEY `more_index` (`id`,`name`,`gender`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

# 创建空间索引
mysql> create table stu_id_index5
-> (id int,
-> name varchar(20),
-> gender enum('男','女') default '男',
-> hobby geometry not null,
-> spatial index space_index(hobby))
-> ENGINE=MyISAM DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.00 sec)

mysql> show create table stu_id_index5\G
*************************** 1. row ***************************
Table: stu_id_index5
Create Table: CREATE TABLE `stu_id_index5` (
`id` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`gender` enum('男','女') DEFAULT '男',
`hobby` geometry NOT NULL,
SPATIAL KEY `space_index` (`hobby`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

注:1、全文索引,只能给char、varchar、text类型的字段创建;
2、创建多列索引时一定要特别注意,只有使用了索引中的第一个字段时才会触发索引。如果没有使用索引中的第一个字段,那么这个多列索引就不会起作用

3、创建空间索引时,表的存储引擎必须是myisam类型,而且索引字段必须有非空约束。空间数据类型包括geometry,point,linestring和polygon类型等;

2、已经存在的表创建索引

使用"create index""创建

# 创建学生表
mysql> create table student
-> (id int primary key auto_increment,
-> name varchar(20),
-> gender enum('男','女') default '男',
-> hobby geometry not null);
Query OK, 0 rows affected (0.01 sec)
# 查看学生表结构
mysql> desc student;
+--------+-------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | YES | | NULL | |
| gender | enum('男','女') | YES | | 男 | |
| hobby | geometry | NO | | NULL | |
+--------+-------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)


# 创建普通索引
mysql> create index ordinary_index
-> on student(name);
Query OK, 0 rows affected (0.00 sec)

mysql> show create table student\G
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`gender` enum('男','女') DEFAULT '男',
`hobby` geometry NOT NULL,
PRIMARY KEY (`id`),
KEY `ordinary_index` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

# 创建唯一索引
mysql> create unique index unique_index
-> on student(id);
Query OK, 0 rows affected (0.01 sec)

mysql> show create table student\G
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`gender` enum('男','女') DEFAULT '男',
`hobby` geometry NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_index` (`id`),
KEY `ordinary_index` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> create fulltext index full_index
-> on student(name);
Query OK, 0 rows affected, 1 warning (0.48 sec)

mysql> show create table student\G
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`gender` enum('男','女') DEFAULT '男',
`hobby` geometry NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_index` (`id`),
KEY `ordinary_index` (`name`),
FULLTEXT KEY `full_index` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

# 创建多列索引
mysql> create index more_index on student(id,name,gender);
Query OK, 0 rows affected (0.00 sec)

mysql> show create table student\G
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`gender` enum('男','女') DEFAULT '男',
`hobby` geometry NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_index` (`id`),
KEY `ordinary_index` (`name`),
KEY `more_index` (`id`,`name`,`gender`),
FULLTEXT KEY `full_index` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

# 创建空间索引
mysql> create spatial index space_index on student(hobby);
Query OK, 0 rows affected (0.01 sec)

mysql> show create table student\G
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`gender` enum('男','女') DEFAULT '男',
`hobby` geometry NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_index` (`id`),
KEY `ordinary_index` (`name`),
KEY `more_index` (`id`,`name`,`gender`),
SPATIAL KEY `space_index` (`hobby`),
FULLTEXT KEY `full_index` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

使用"alter table""创建

# 创建student表
mysql> create table student
-> (id int primary key auto_increment,
-> name varchar(20),
-> gender enum('男','女') default '男',
-> hobby geometry not null);
Query OK, 0 rows affected (0.01 sec)

# 查看表结构
mysql> desc student;
+--------+-------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | YES | | NULL | |
| gender | enum('男','女') | YES | | 男 | |
| hobby | geometry | NO | | NULL | |
+--------+-------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

# 创建普通索引
mysql> alter table student
-> add index ordinary_index(name);
Query OK, 0 rows affected (0.00 sec)
mysql> show create table student\G
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`gender` enum('男','女') DEFAULT '男',
`hobby` geometry NOT NULL,
PRIMARY KEY (`id`),
KEY `ordinary_index` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

# 创建惟一索引
mysql> alter table student
-> add unique unique_index(id);
Query OK, 0 rows affected (0.01 sec)

mysql> show create table student\G
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`gender` enum('男','女') DEFAULT '男',
`hobby` geometry NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_index` (`id`),
KEY `ordinary_index` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

# 创建全文索引
mysql> alter table student
-> add fulltext index full_index(name);
Query OK, 0 rows affected, 1 warning (6.07 sec)

mysql> show create table student\G
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`gender` enum('男','女') DEFAULT '男',
`hobby` geometry NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_index` (`id`),
KEY `ordinary_index` (`name`),
FULLTEXT KEY `full_index` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.01 sec)

# 创建多列索引
mysql> alter table student
-> add index more_index(id,name,gender);
Query OK, 0 rows affected (0.01 sec)

mysql> show create table student\G
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`gender` enum('男','女') DEFAULT '男',
`hobby` geometry NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_index` (`id`),
KEY `ordinary_index` (`name`),
KEY `more_index` (`id`,`name`,`gender`),
FULLTEXT KEY `full_index` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

# 创建空间索引
mysql> alter table student
-> add spatial index space_index(hobby);
Query OK, 0 rows affected (0.01 sec)

mysql> show create table student\G
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`gender` enum('男','女') DEFAULT '男',
`hobby` geometry NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_index` (`id`),
KEY `ordinary_index` (`name`),
KEY `more_index` (`id`,`name`,`gender`),
SPATIAL KEY `space_index` (`hobby`),
FULLTEXT KEY `full_index` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

删除索引

# 查看student表的索引
mysql> show create table student\G
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`gender` enum('男','女') DEFAULT '男',
`hobby` geometry NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_index` (`id`),
KEY `ordinary_index` (`name`),
KEY `more_index` (`id`,`name`,`gender`),
SPATIAL KEY `space_index` (`hobby`),
FULLTEXT KEY `full_index` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

# 删除student所有索引
mysql> drop index unique_index on student;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> drop index ordinary_index on student;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> drop index more_index on student;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> drop index space_index on student;
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> drop index full_index on student;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0

# 查看student表的索引
mysql> show create table student\G
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`gender` enum('男','女') DEFAULT '男',
`hobby` geometry NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

单列索引、普通索引的创建方法相同。

三、索引 案例实战

1、在数据库job下创建work_info表。创建表的同时在id字段上创建名为index_id的唯一性索引,而且以降序的格式排列。
# workInfo表内容如下所示
字段描述 数据类型 主键 外键 非空 唯一 自增
id 编号 INT(10) 是 否 是 是 是
name 职位名称 VARCHAR(20) 否 否 是 否 否
type 职位类别 VARCHAR(10) 否 否 否 否 否
address 工作地址 VARCHAR(50) 否 否 否 否 否
wage 工资 INT 否 否 否 否 否
contents 工作内容 TINYTEXT 否 否 否 否 否
extra 附加信息 TEXT 否 否 否 否 否

# 创建work_info表
mysql> create table work_info
-> (id int primary key auto_increment,
-> name varchar(20) not null,
-> type varchar(10),
-> address varchar(50),
-> tel varchar(20),
-> wage int,
-> content tinytext,
-> extra text,
-> unique index index_id(id desc));
Query OK, 0 rows affected (0.05 sec)

# 查看表结构
mysql> desc work_info;
+---------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| type | varchar(10) | YES | | NULL | |
| address | varchar(50) | YES | | NULL | |
| tel | varchar(20) | YES | | NULL | |
| wage | int(11) | YES | | NULL | |
| content | tinytext | YES | | NULL | |
| extra | text | YES | | NULL | |
+---------+-------------+------+-----+---------+----------------+
8 rows in set (0.00 sec)

# 查看建表语句
mysql> show create table work_info\G
*************************** 1. row ***************************
Table: work_info
Create Table: CREATE TABLE `work_info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`type` varchar(10) DEFAULT NULL,
`address` varchar(50) DEFAULT NULL,
`tel` varchar(20) DEFAULT NULL,
`wage` int(11) DEFAULT NULL,
`content` tinytext,
`extra` text,
PRIMARY KEY (`id`),
UNIQUE KEY `index_id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

2、使用create index语句为name字段创建长度为10的索引index_name
mysql> create index index_name on work_info(name(10));
Query OK, 0 rows affected (0.01 sec)

mysql> show create table work_info\G
*************************** 1. row ***************************
Table: work_info
Create Table: CREATE TABLE `work_info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`type` varchar(10) DEFAULT NULL,
`address` varchar(50) DEFAULT NULL,
`tel` varchar(20) DEFAULT NULL,
`wage` int(11) DEFAULT NULL,
`content` tinytext,
`extra` text,
PRIMARY KEY (`id`),
UNIQUE KEY `index_id` (`id`),
KEY `index_name` (`name`(10))
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

3、使用alter table语句在type和address上创建名为index_t的索引
mysql> alter table work_info
-> add index index_t(type,address);
Query OK, 0 rows affected (0.00 sec)

mysql> show create table work_info\G
*************************** 1. row ***************************
Table: work_info
Create Table: CREATE TABLE `work_info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`type` varchar(10) DEFAULT NULL,
`address` varchar(50) DEFAULT NULL,
`tel` varchar(20) DEFAULT NULL,
`wage` int(11) DEFAULT NULL,
`content` tinytext,
`extra` text,
PRIMARY KEY (`id`),
UNIQUE KEY `index_id` (`id`),
KEY `index_name` (`name`(10)),
KEY `index_t` (`type`,`address`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

4、将workInfo表的存储引擎更改为MyISAM类型
mysql> alter table work_info
-> engine=myisam;
Query OK, 0 rows affected (0.01 sec)

mysql> show create table work_info\G
*************************** 1. row ***************************
Table: work_info
Create Table: CREATE TABLE `work_info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`type` varchar(10) DEFAULT NULL,
`address` varchar(50) DEFAULT NULL,
`tel` varchar(20) DEFAULT NULL,
`wage` int(11) DEFAULT NULL,
`content` tinytext,
`extra` text,
PRIMARY KEY (`id`),
UNIQUE KEY `index_id` (`id`),
KEY `index_name` (`name`(10)),
KEY `index_t` (`type`,`address`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

5、使用alter table语句在extra字段上创建名为index_ext的全文索引
mysql> alter table work_info
-> add fulltext index index_ext(extra);
Query OK, 0 rows affected (0.00 sec)

mysql> show create table work_info\G
*************************** 1. row ***************************
Table: work_info
Create Table: CREATE TABLE `work_info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`type` varchar(10) DEFAULT NULL,
`address` varchar(50) DEFAULT NULL,
`tel` varchar(20) DEFAULT NULL,
`wage` int(11) DEFAULT NULL,
`content` tinytext,
`extra` text,
PRIMARY KEY (`id`),
UNIQUE KEY `index_id` (`id`),
KEY `index_name` (`name`(10)),
KEY `index_t` (`type`,`address`),
FULLTEXT KEY `index_ext` (`extra`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

6、删除workInfo表的唯一性索引index_id
mysql> drop index index_id on work_info;
Query OK, 0 rows affected (0.01 sec)

mysql> show create table work_info\G
*************************** 1. row ***************************
Table: work_info
Create Table: CREATE TABLE `work_info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`type` varchar(10) DEFAULT NULL,
`address` varchar(50) DEFAULT NULL,
`tel` varchar(20) DEFAULT NULL,
`wage` int(11) DEFAULT NULL,
`content` tinytext,
`extra` text,
PRIMARY KEY (`id`),
KEY `index_name` (`name`(10)),
KEY `index_t` (`type`,`address`),
FULLTEXT KEY `index_ext` (`extra`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
1 row in set (0.00 sec)