一、索引简介
索引是一种特殊的数据结构,由数据库中一列或多列组合而成,用来快速查询数据库表中的特定记录。索引是提高数据库性能的重要方式。MySQL中,所有的数据类型都可以被索引。MySQL的索引包括普通索引、唯一性索引、全文索引、单列索引、多列索引和空间索引等。
1、索引的含义和特点
索引是创建在表上的,是对数据库表中一列或多列的值进行排序的一种结构。
通过索引,查询数据时可以不必读完记录的所有信息,而只是查询索引列。否则,数据库系统将读取每条记录的所有信息进行匹配。
不同的存储引擎定义了每个表的最大索引数和最大索引长度。所有存储引擎对每个表至少支持16个索引,总索引长度至少为256字节。索引有两种存储类型,包括 B 型树(BTREE) 索引和哈希(HASH) 索引。InnoDB 和 MyISAM 存储引擎支持 BTREE 索引,MEMORY存储引擎支持HASH 索引和BTREE 索引,默认为前者。
索引的优点是提高检索数据的速度;对有依赖关系的子表和父表之间的联合查询时,可以提高查询速度;使用分组和排序子句进行数据查询,同样可以节省查询中分组和排序的时间。
索引的缺点是创建和维护索引耗费时间,耗费时间的数量随着数据的增加而增加;索引需要占用物理空间,每一个索引要占一定的物理空间;增加、删除和修改数据时,要动态的维护索引,造成数据的维护速度降低了。
技巧:索引可以提高查询的速度,但是会影响插入记录的速度。因为,向有索引的表中插入记录时,数据库系统会按照索引进行排序。这样就降低了插入记录的速度,插入大量记录时的速度影响更明显。这种情况下,最好的办法是先删除索引,然后插入数据。插入完成后,再创建索引。
2、索引的分类
MySQL 的索引包括普通索引、唯一性索引、全文索引、单列索引、多列索引、空间索引等。
2.1 普通索引
在创建普通索引时,不附加任何限制条件。这类索引可以创建在任何数据类型中,其值是否唯一和非空由字段本身的完整性约束条件决定。
2.2 唯一性索引
使用UNIQUE 参数可以设置索引为唯一索引。在创建唯一性索引时,限制该索引的值必须是唯一的。
2.3 使用FULLTEXT 参数可以设置索引为全文索引。全文索引只能创建在 CHAR、VARCHAR 或TEXT 类型的字段上。
2.4 单列索引
在表中的单个字段上创建索引。单列索引只根据该字段进行索引。单列索引可以是普通索引、唯一性索引,还可以是全文索引。只要保证该索引只对应一个字段即可。
2.5 多列索引
在表的多个字段上创建索引。该索引指向创建时对应的多个字段,可以通过这几个字段进行查询。但是,只有查询条件中使用了这些字段的第一个字段时,索引才会被使用。
2.6 空间索引
使用SPATIAL 参数可以设置索引为空间索引。空间索引只能建立在空间数据类型上,这样可以提高系统获取空间数据的效率。MySQL中的空间数据类型包括GEOMETRY和POINT、LINESTRING、POLYGON等。目前只有MyISAM存储引擎支持空间检索,而且索引的字段不能为空值。
3、索引的设计原则
3.1 选择唯一性索引
3.2 为经常需要排序、分组和联合操作的字段建立索引
3.3 为常作为查询条件的字段建立索引
3.4 限制索引的数目
3.5 尽量使用数据量少的索引
3.6 尽量使用前缀来索引
3.8 删除不再使用或者很少使用的索引
二、创建索引
创建索引是指在某个表的一列或多列上建立一个索引,以便提高对表的访问速度。创建索引有3种方式:创建表的时候创建索引、在已经存在的表上创建索引、使用 ALTER TABLE语句创建索引。
1、创建表的时候创建索引
创建表时可以直接创建索引,这种方式最简单、方便。其基本语法如下:
CREATE TABLE 表名 (属性名 数据类型 [完整性约束条件],
属性名 数据类型 [完整性约束条件],
....
属性名 数据类型
[UNIQUE | FULLTEXT | SPATIAL] INDEX | KEY
[别名] ( 属性名1 [(长度)] [ASC | DESC])
);
其中,UNIQUE 是可选参数,表示索引为唯一索引;FULLTEXT 是可选参数,表示索引为全文索引;SPATIAL 也是可选参数,表示索引为空间索引;INDEX 和 KEY 参数用来指定字段为索引的,两者作用相同,选择其中之一就可以了; 别名 是可选参数,用来给创建的索引取的新名称;属性名1 参数指定索引对应的字段的名称,该字段必须为前面定义好的字段;长度 是可选参数,其指索引的长度,必须是字符串类型才可以使用;ASC 和 DESC 都是可选参数,ASC 参数表示升序排列,DESC 参数表示降序排列。
1.1 创建普通索引
创建一个普通索引,不需要加任何 UNIQUE、FULLTEXT、SPATIAL 参数。
创建一个表名为index1的表,在表中的id字段上建立索引如下:
mysql> CREATE TABLE index1(id INT,
-> name VARCHAR(20).
-> sex BOOLEAN,
-> INDEX(id)
-> );
mysql> SHOW CREATE TABLE index1 G
*************************** 1. row ***************************
Table: index1
Create Table: CREATE TABLE `index1` (
`id` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`sex` tinyint(1) DEFAULT NULL,
KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.02 sec)
结果显示id字段上已经建立了一个名为 id 的索引。使用EXPLAIN 语句可以查看索引是否被使用,如下:
mysql> EXPLAIN SELECT * FROM index1 where id=1 G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: index1
partitions: NULL
type: ref
possible_keys: id
key: id
key_len: 5
ref: const
rows: 1
filtered: 100.00
Extra: NULL
1 row in set, 1 warning (0.06 sec)
上面的结果显示,possible_key 和 key 处的值都为 id 。说明 id 索引已经存在,而且已经开始起作用。
1.2 创建唯一性索引
创建唯一性索引时,需要使用 UNIQUE 参数进行约束。
创建表名为index2的表,在表中的 id 字段上建立名为 index2_id 的唯一性索引,且以升序的形式排列。SQL代码如下:
mysql> CREATE TABLE index2(id INT UNIQUE,
-> name VARCHAR(20),
-> UNIQUE INDEX index2_id(id ASC)
-> );
1.3 创建全文索引
全文索引只能创建在 CHAR、VARCHAR 或 TEXT 类型的字段上。
创建一个表名为index3 的表,在表中的info 字段上建立名为 index3_info 的全文索引。SQL 代码如下:
mysql> CREATE TABLE index3(id INT,
-> info VARCHAR(20),
-> FULLTEXT INDEX index3_info(info)
-> )ENGINE=MyISAM;
1.4 创建单列索引
单列索引是在表的单个字段上创建索引。
创建一个表名为index4 的表,在表中的subject 字段上建立名为 index4_st 的单列索引。SQL代码如下:
mysql> CREATE TABLE index4(id INT,
-> subject VARCHAR(30),
-> INDEX index4_st(subject(10))
-> );
仔细观察会发现 subject 字段长度为30,而index_st 索引的长度只有10,这是对于字符型的数据,可以不用查询全部信息,而只查询其前面的若干字符信息,这样做可以提高查询速度。
1.5 创建多列索引
创建多列索引是在表的多个字段上创建一个索引。
创建一个表名为index5 的表,在表中的name 和sex 字段上建立名为index5_ns 的多列索引。SQL 代码如下:
mysql> CREATE TABLE index5(id INT,
-> name VARCHAR(20),
-> sex CHAR(4),
-> KEY index5_ns(name,sex)
-> );
下面使用EXPLAIN语句查看索引的使用情况,分别用name字段和sex字段作为查询条件进行查询,会发现只有使用了这些字段中的第一个字段(name)时才会触发索引。
mysql> EXPLAIN select * from index5 where name='hj' G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: index5
partitions: NULL
type: ref
possible_keys: index5_ns
key: index5_ns
key_len: 63
ref: const
rows: 1
filtered: 100.00
Extra: NULL
1 row in set, 1 warning (0.01 sec)
mysql> EXPLAIN select * from index5 where sex='man' G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: index5
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 1
filtered: 100.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)
1.6 创建空间索引
创建空间索引时必须使用 SPATIAL 参数来设置。创建空间索引时,表的存储引擎必须是MySIAM 类型。而且,索引字段必须有非空约束。
创建一个表名为 index6 的表,在表中的 space 字段上建立名为 index6_sp 的空间索引。SQL 代码如下:
mysql> CREATE TABLE index6(id INT,
-> space GEOMETRY NOT NULL,
-> SPATIAL KEY index6_sp(space)
-> )ENGINE=MyISAM;
其中space字段是非空的,而且数据类型是GEOMETRY类型,这个类型是空间数据类型。空间数据类型包括GEOMETRY、POINT、LINESTRING、POLYGON类型等。这些空间数据类型平时很少用到。
2、在已经存在的表上创建索引
在已经存在的表中,可以直接为表上的一个或几个字段创建索引。基本语法如下:
CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX 索引名 ON 表名 (属性名 [(长度)] [ASC | DESC];
其中,UNIQUE 是可选参数,表示索引为唯一性索引;FULLTEXT 是可选参数,表示索引为全文索引;SPATIAL 也是可选参数,表示索引为空间索引;INDEX 参数用来指定字段为索引的;索引名 参数是给创建的索引取的新名称;表名 参数是指需要创建索引的表的名称,该表必须是已经存在的,如果不存在,需要先创建;属性名 参数指定索引对应的字段的名称,该字段必须为前面定义好的字段;长度 是可选参数,其指索引的长度,必须是字符串类型才可使用;ASC 和DESC 都是可选参数,ASC 参数表示升序排列,DESC 参数表示降序排列。
mysql> CREATE INDEX index7_id ON example2(stu_id); 在example2 表中的stu_id 字段上建立名为index7_id 的索引
mysql> CREATE UNIQUE INDEX index8_id ON example2(course_id); 在example2 表中的course_id字段上建立名为index8_id的唯一性索引
mysql> CREATE FULLTEXT INDEX index9_info ON example2(info); 在example2 表中的info字段上建立名为index9_info的全文索引。其中FULLTEXT 用来设置索引为全文索引;info字段必须为CHAR、VARCHAR 和 TEXT 等类型。
mysql> CREATE INDEX index10_addr ON study(address(4)); 在sutdy表中的address字段上建立名为index10_addr的单列索引,查询时可以只查询address字段的前4个字符,而不需要全部查询。
mysql> CREATE INDEX index11_na ON study(name,address); 在sutdy表中的name 和 address 字段上建立名为index11_na 的多列索引。查询条件中必须有 name 字段才能使用索引。
mysql> CREATE SPATIAL INDEX index12_line ON study(line); 在sutdy表中的line 字段上建立名为index12_line的空间索引,其中SPATIAL 用来设置索引为空间索引;表 index12的存储引擎必须是MyISAM类型;line字段必须为空间数据类型,而且是非空的。
3、用 ALTER TABLE 语句来创建索引
在已经在存在的表上,可以通过 ALTER TABLE 语句直接为表上的一个或几个字段创建索引。基本语法如下:
ALTER TABLE 表名 ADD [UNIQUE | FULLTEXT | SPATIAL] INDEX 索引名 (属性名 [(长度)] [ASC | DESC]);
其中参数与上面的两种方式的参数是一样的。
三、删除索引
删除索引是指将表中已经存在的索引删除掉。对于一些不使用会降低表的更新速度,影响数据库性能的索引,应该将其删除。
通过DROP语句来删除索引。其基本语法如下:
DROP INDEX 索引名 ON 表名;
mysql> DROP INDEX index10_addr ON study; 删除 study 表的索引 index10_addr。