目录
一、索引概述
索引是对数据库表中的一列或多列的值进行排序的一种结构,使用索引可提高数据库中特定的数据的查询速度。索引是一个单独的、存储在磁盘上的数据结构,它们包含着对数据表里所有记录的引用指针。使用索引用于快速找出在某个或多个列有一特定值的行,所有MySQL列类型都可以被索引,对相关列使用索引是提高查询操作速度的最佳途径。
索引是在存储引擎中实现的,每种存储引擎的索引是不同的,并每种存储索引不一定支持全部索引。所有存储引擎至少支持16个索引,总索引长度至少为256字节。MySQL中索引的存储类型有两种:BTREE和HASH。MyISAM和InnoDB存储引擎只支持BTREE索引,MEMORY和HEAP存储引擎可以支持HASH和BTREE索引。
二、索引的优缺点
1、优点
1)通过创建唯一索引,可以保证数据库表中每一行数据的唯一性。
2)可以大大加快数据的查询速度,这也是创建索引的最主要原因。
3)在实现数据的参考完整性方面,可以加速表与表之间的连接速度。
4)在使用分组和排序子句进行数据查询时,也可以显著减少查询中分组和排序的时间。
2、缺点
1)创建索引和维护索引需要耗费时间,并随着数据量的增加消耗的时间也会增加。
2)索引需要占磁盘空间,除了数据表占数据空间之外,每个索引还需要占用一定的物理空间,如果有大量的索引,索引文件可能比数据文件更快达到最大文件尺寸。
3)当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。
三、索引的分类
1、普通索引和唯一索引
普通索引就是MySQL基本的索引类型,允许定义索引列插入重复值和空值。
唯一索引定义列的值必须唯一,允许为空,主键索引是特殊的唯一索引,但是主键索引不允许有空值。
2、单列索引和组合索引
单列索引只包含一列,一个表中可以有多个单列索引。
组合索引只在表中多个字段组合上创建索引,只有在查询条件中使用了这些字段的左边字段时,索引才会被使用,使用组合索引时遵循最左前缀集合。
3、全文索引
全文索引类型为FULLTEXT,在定义索引列上支持值得全文查找,允许这些索引列中插入重复得值和空值,全文所有只有MyISAM存储引擎支持全文索引。全文索引可以在CHAR、VARCHAR、TEXT类型的列上创建。
4、空间索引
空间索引是对空间数据类型的字段建立的索引,MySQL的空间数据类型有4种,分别是GEOMETRY、POINT、LINESTRING、POLYGON。MySQL使用SPATIAL关字扩展,创建空间索引必须声明列为NOT NULL,只能创建在MyISAM存储引擎中。
四、索引设计原则
1)索引并非越多越好,大量索引不仅占用磁盘空间,而且还影响INSERT、UPDATE等语句的性能,因为当表中的数据在更改时,索引也会进行调整和更新。
2)数据量小的表最好不要使用索引,由于数据较少,查询花费的时间可能比遍历索引的时间还要短,索引可能不会产生优化效果。
3)避免对经常更新的表进行过多的索引,并且索引的列尽可能少。而对经常用于查询的字段应该创建索引,但要避免添加不必要的字段。
4)在不同值很少的列上不要建立索引,应该建在不同值较多的列上建立索引,这样才会加快查询速度。
5)当唯一索引时某种书库本身的特征时,指定唯一索引,使用唯一索引需能确保定义的列的数据完整性,以提高查询速度。
6)在频繁进行排序或分组的列上建立索引,如果待排序的列有多个,可以在这些列上建立组合索引。
五、创建索引
1、在创建表时创建索引
基本语法
sql
create table 表名(
字段名1 数据类型 [约束条件等]
字段名2 数据类型 [约束条件等]
......
[unique|fulltext|spatial] [index|key] [索引名] [字段名 [长度] [ASC|DESC]]
);
unique---唯一索引;
fulltext---全文索引;
spatial---空间索引;
index|key---作用相同,用来创建的索引;
长度---只有字符串类型才可以指定索引的长度。
1)、创建普通索引
sql
mysql> create table test_a(
id int not null,
name varchar(255),
age int,
index(id)
);
Query OK, 0 rows affected (0.01 sec)
2)、创建唯一索引
sql
mysql> create table test_b(
id int not null,
name varchar(255),
age int,
unique index unique_index(id)
);
Query OK, 0 rows affected (0.01 sec)
3)、创建单索引
sql
mysql> create table test_c(
id int not null,
name varchar(255),
age int,
index single_index(name) );
Query OK, 0 rows affected (0.01 sec)
4)、创建组合索引
sql
mysql> create table test_d(
id int not null,
name varchar(255),
age int,
index multi_index(id,name) );
Query OK, 0 rows affected (0.01 sec)
5)、创建全文索引
sql
mysql> create table test_e(
id int not null,
name varchar(255),
age int,
fulltext index fulltext_index(name) );
Query OK, 0 rows affected (0.13 sec)
6)、创建空间索引
sql
mysql> create table test_f(
id geometry not null,
name varchar(255),
age int,
spatial index spatial_index(id) )engine=MyISAM;
Query OK, 0 rows affected (0.00 sec)
2、已存在的表上创建索引
基本语法1
sql
alter table 表名 add [unique | fulltext | spatial]
[index | key] [索引名](字段名)[长度] [asc | desc];
基本语法2
sql
create [unique | fulltext | spatial] index 索引名
on 表名 (字段名[长度]) [ASC | DESC];
在添加时,定义给上面建表时创建类似。
六、查看/删除索引
1、查看索引
方法一:查询索引
sql
show create table 表名 \G
例如
sql
mysql> show create table test_a \G
*************************** 1. row ***************************
Table: test_a
Create Table: CREATE TABLE `test_a` (
`id` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
方法二:查询某张表中的索引情况
sql
show index from 表名;
例如
sql
mysql> show index from test_a;
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| test_a | 1 | id | 1 | id | A | 0 | NULL | NULL | | BTREE | | |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)
方法三:查看使用计划查询SQL使用索引情况
sql
explain select 字段列表 from 表名 [where <条件表达式>] \G
例如
sql
mysql> explain select * from test_b where id=1 \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: test_b
partitions: NULL
type: const
possible_keys: unique_index
key: unique_index
key_len: 4
ref: const
rows: 1
filtered: 100.00
Extra: NULL
1 row in set, 1 warning (0.00 sec)
2、删除索引
语法1
sql
drop index 索引名 on 表名
语法2
sql
alter table 表名 drop index 索引名;
例如
sql
#先查看表的索引
mysql> show index from test_a;
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| test_a | 1 | id | 1 | id | A | 0 | NULL | NULL | | BTREE | | |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)
#删除指定索引
mysql> drop index id on test_a;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
#查看是否被删除
mysql> show index from test_a;
Empty set (0.00 sec)
七、索引练习
素材
sql
+------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+----------------+
| goods_id | int(11) | NO | PRI | NULL | auto_increment |
| goods_name | varchar(20) | NO | | | |
| cat_id | int(11) | NO | | 0 | |
| brand_id | int(11) | NO | | 0 | |
| goods_sn | char(12) | NO | | | |
| shop_price | float(6,2) | NO | | 0.00 | |
| goods_desc | text | YES | | NULL | |
+------------+-------------+------+-----+---------+----------------+
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| cat_id | int(11) | NO | PRI | NULL | auto_increment |
| cate_name | varchar(20) | NO | | | |
| parent_id | int(11) | NO | | 0 | |
+-----------+-------------+------+-----+---------+----------------+
1、建立一个utf8编码的数据库test1
sql
mysql> create database test1 charset=utf8;
Query OK, 1 row affected (0.00 sec)
mysql> use test1;
Database changed
2、建立商品表goods和栏目表category
如上表结构创建表:存储引擎engine myisam 字符集charset utf8
sql
mysql> create table goods(
goods_id int(11) primary key auto_increment,
goods_name varchar(20) not null,
cat_id int(11) not null default 0,
brand_id int(11) not null default 0,
goods_sn char(12) not null,
shop_price float(6,2) not null default 0.00,
goods_desc text
)engine=MyISAM,charset=utf8;
Query OK, 0 rows affected (0.00 sec)
mysql> create table category (
cat_id int(11) primary key auto_increment,
cate_name varchar(20) not null,
parent_id int not null default 0
)engine=MyISAM,charset=utf8;
Query OK, 0 rows affected (0.00 sec)
3、在 goods_name 列上加唯一性索引(用alter table方式)
sql
mysql> alter table goods add unique index unique_index(goods_name);
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show index from goods;
+-------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| goods | 0 | PRIMARY | 1 | goods_id | A | 0 | NULL | NULL | | BTREE | | |
| goods | 0 | unique_index | 1 | goods_name | A | 0 | NULL | NULL | | BTREE | | |
+-------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec)
4、在 shop_price 列上加普通索引(用create index方式)
sql
mysql> create index shop_price_index on goods(shop_price);
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show index from goods;
+-------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| goods | 0 | PRIMARY | 1 | goods_id | A | 0 | NULL | NULL | | BTREE | | |
| goods | 0 | unique_index | 1 | goods_name | A | 0 | NULL | NULL | | BTREE | | |
| goods | 1 | shop_price_index | 1 | shop_price | A | NULL | NULL | NULL | | BTREE | | |
+-------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set (0.00 sec)
5、在表category中cat_id上增加普通索引,然后再删除 (分别使用drop index和alter table删除)
sql
#建立普通索引
mysql> alter table category add index index_cat_id(cat_id);
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
#查看建立成功没有
mysql> show index from category;
+----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| category | 0 | PRIMARY | 1 | cat_id | A | 0 | NULL | NULL | | BTREE | | |
| category | 1 | index_cat_id | 1 | cat_id | A | NULL | NULL | NULL | | BTREE | | |
+----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec)
#使用drop index删除索引
mysql> drop index index_cat_id on category;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
#查看删除成功没有
mysql> show index from category;
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| category | 0 | PRIMARY | 1 | cat_id | A | 0 | NULL | NULL | | BTREE | | |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)
#再创建索引
mysql> alter table category add index index_cat_id(cat_id);
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
#查看创建成功没有
mysql> show index from category;
+----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| category | 0 | PRIMARY | 1 | cat_id | A | 0 | NULL | NULL | | BTREE | | |
| category | 1 | index_cat_id | 1 | cat_id | A | NULL | NULL | NULL | | BTREE | | |
+----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec)
#使用alter table 删除索引
mysql> alter table category drop index index_cat_id;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
#查看删除成功没有
mysql> show index from category;
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| category | 0 | PRIMARY | 1 | cat_id | A | 0 | NULL | NULL | | BTREE | | |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)
参考书籍:MySQL5.7从入门到精通-清华大学出版社