(2)Mysql ---- 索引ABC 《MYSQL 5.5从零开始学》笔记

索引是一种特殊的数据库结构,可以用来快速查询数据库表中的特定记录索引是提高数据库性能的重要方式

MySQL中,所有的数据类型都可以被索引。

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

7.1  索引简介

索引由数据库表中一列或多列组合而成,其作用是提高对表中数据的查询速度。本节将详细讲解索引的含义、作用、分类和设计索引的原则

7.1.1  索引的含义和特点

索引是创建在表上的,是对数据库表中一列或多列的值进行排序的一种结构。索引可以提高查询的速度。本小节将详细讲解索引的含义、作用和优缺点。

通过索引,查询数据时可以不必读完记录的所有信息,而只是查询索引列。否则,数据库系统将读取每条记录的所有信息进行匹配。


例如,索引相当于新华字典的音序表。如果要查"库"字,如果不使用音序,需要从字典的400页中逐页来找。但是,如果提取拼音出来,构成音序表,就只需要从10多页的音序表中直接查找。这样就可以大大节省时间。因此,使用索引可以很大程度上提高数据库的查询速度。这样有效的提高了数据库系统的性能。

不同的存储引擎定义了每个表的最大索引数和最大索引长度所有存储引擎对每个表至少支持16个索引,总索引长度至少为256字节。有些存储引擎支持更多的索引数和更大的索引长度。索引有两种存储类型,包括B型树(BTREE)索引和哈希(HASH)索引

InnoDB和MyISAM存储引擎支持BTREE索引,MEMORY存储引擎支持HASH索引和BTREE索引,默认为前者。

索引有其明显的优势,也有其不可避免的缺点。

索引的优点

 (1)可以提高检索数据的速度,这是创建索引的最主要的原因;

 (2)对于有依赖关系的子表和父表之间的联合查询时,可以提高查询速度;

 (3)使用分组和排序子句进行数据查询时,同样可以显著节省查询中分组和排序的时间。

索引的缺点

(1)创建和维护索引需要耗费时间,耗费时间的数量随着数据量的增加而增加;

(2)索引需要占用物理空间,每一个索引要占一定的物理空间;

(3)增加、删除和修改数据时,要动态的维护索引,造成数据的维护速度降低了 。

因此,选择使用索引时,需要综合考虑索引的优点和缺点。

技巧:索引可以提高查询的速度,但是会影响插入记录的速度。因为,向有索引的表中插入记录时,数据库系统会按照索引进行排序。这样就降低了插入记录的速度,插入大量记录时的速度影响更加明显。这种情况下,最好的办法是先删除表中的索引,然后插入数据。插入完成后,再创建索引。

7.1.2  索引的分类

MySQL的索引包括普通索引和唯一性索引、单列索引和多列索引全文索引和空间索引等。本小节将详细讲解这几种索引的含义和特点。

1.普通索引

在创建普通索引时,不附加任何限制条件。这类索引可以创建在任何数据类型中,其值是否唯一和非空由字段本身的完整性约束条件决定。建立索引以后,查询时可以通过索引进行查询。例如,在student表的stu_id字段上建立一个普通索引。查询记录时,就可以根据该索引进行查询。

2.唯一性索引

使用UNIQUE参数可以设置索引为唯一性索引。在创建唯一性索引时,限制该索引的值必须是唯一的。例如,在student表的stu_name字段中创建唯一性索引,那么stu_name字段的值就必需是唯一的。通过唯一性索引,可以更快速地确定某条记录。主键就是一种特殊唯一性索引。

3.全文索引

使用FULLTEXT参数可以设置索引为全文索引。全文索引只能创建在CHAR、VARCHAR或TEXT类型的字段上。查询数据量较大的字符串类型的字段时,使用全文索引可以提高查询速度。例如,student表的information字段是TEXT类型,该字段包含了很多的文字信息。在information字段上建立全文索引后,可以提高查询information字段的速度。MySQL数据库从3.23.23版开始支持全文索引,但只有MyISAM存储引擎支持全文检索。在默认情况下,全文索引的搜索执行方式不区分大小写。但索引的列使用二进制排序后,可以执行区分大小写的全文索引。

4.单列索引

在表中的单个字段上创建索引。单列索引只根据该字段进行索引。单列索引可以是普通索引,也可以是唯一性索引,还可以是全文索引。只要保证该索引只对应一个字段即可。

5.多列索引(组合索引)

多列索引是在表的多个字段上创建一个索引。该索引指向创建时对应的多个字段,可以通过这几个字段进行查询。但是,只有查询条件中使用了这些字段中第一个字段时,索引才会被使用。例如,在表中的id、name和sex字段上建立一个多列索引,那么,只有查询条件使用了id字段时该索引才会被使用。(最左前缀原则)

6.空间索引

使用SPATIAL参数可以设置索引为空间索引。空间索引只能建立在空间数据类型上,这样可以提高系统获取空间数据的效率。MySQL中的空间数据类型包括GEOMETRY和POINT、LINESTRING和POLYGON等。目前只有MyISAM存储引擎支持空间检索,而且索引的字段不能为空值。对于初学者来说,这类索引很少会用到。

7.1.3  索引的设计原则

为了使索引的使用效率更高,在创建索引时,必须考虑在哪些字段上创建索引和创建什么类型的索引。


7.2  创建索引

创建索引是指在某个表的一列或多列上建立一个索引,以便提高对表的访问速度。创建索引有3种方式,这3种方式分别是

(1)在创建表的时候创建索引、(2)在已经存在的表上创建索引create(3)使用ALTER TABLE语句来创建索引。

------------------------------------------------------------------------

7.2.1  创建表的时候创建索引

创建表时可以直接创建索引,这种方式最简单、方便。其基本形式如下:

 
 
  1. CREATE TABLE  表名 ( 属性名 数据类型 [完整性约束条件],  
  2. 属性名 数据类型 [完整性约束条件],  
  3. ......  
  4. 属性名 数据类型  
  5. [ UNIQUE | FULLTEXT | SPATIAL ]  INDEX | KEY  
  6. [ 别名 ]  ( 属性名1  [(长度)]  [ ASC | DESC] )  
  7. ); 

其中,UNIQUE是可选参数,表示索引为唯一性索引;FULLTEXT是可选参数,表示索引为全文索引;SPATIAL也是可选参数,表示索引为空间索引;INDEX和KEY参数用来指定字段为索引的,两者选择其中之一就可以了,作用是一样的;"别名"是可选参数,用来给创建的索引取的新名称;"属性1"参数指定索引对应的字段的名称,该字段必须为前面定义好的字段;"长度"是可选参数,其指索引的长度,必须是字符串类型才可以使用;"ASC"和"DESC"都是可选参数,"ASC"参数表示升序排列,"DESC"参数表示降序排列。

1.创建普通索引

创建一个普通索引时,不需要加任何UNIQUE、FULLTEXT或者SPATIAL参数。

【示例7-1】 下面创建一个表名为index1的表,在表中的id字段上建立索引。SQL代码如下:

 
 
  1. CREATE  TABLE  index1 (
  2. id    INT ,  
  3. name   VARCHAR(20) ,  
  4. sex    BOOLEAN ,  
  5. INDEX ( id)  
  6. ); 

运行结果显示创建成功,使用SHOW CREATE TABLE语句查看表的结构。显示如下:

 
 
  1. mysql> SHOW CREATE TABLE index1 \G  
  2. *************************** 1. row **************************
  3.        Table: index1  
  4. Create Table: CREATE TABLE `index1` (  
  5.   `id` int(11) DEFAULT NULL,  
  6.   `name` varchar(20) DEFAULT NULL,  
  7.   `sex` tinyint(1) DEFAULT NULL,  
  8.   KEY `id` (`id`)  
  9. ENGINE=InnoDB DEFAULT CHARSET=utf8 
  10. 1 row in set (0.00 sec) 

结果可以看到,id字段上已经建立了一个名为id的索引。使用EXPLAIN语句可以查看索引是否被使用,SQL代码如下:

 
 
  1. mysql> EXPLAIN SELECT * FROM index1 where id=1 \G  
  2. *************************** 1. row ************************* 
  3.            id: 1  
  4.   select_type: SIMPLE  
  5.         table: index1  
  6.          type: ref  
  7. possible_keys: id  
  8.           key: id  
  9.       key_len: 5  
  10.           ref: const  
  11.          rows: 1  
  12.         Extra: Using where 
  13. 1 row in set (0.00 sec) 

上面结果显示,possible_keys和key处的值都为id。说明id索引已经存在,而且已经开始起作用

2.创建唯一性索引

创建唯一性索引时,需要使用UNIQUE参数进行约束。

【示例7-2】 下面创建一个表名为index2的表,在表中的id字段上建立名为index2_id的唯一性索引,且以升序的形式排列。SQL代码如下:

 
 
  1. CREATE  TABLE  index2 (
  2. id    INT  UNIQUE ,  
  3. name   VARCHAR(20) ,  
  4. UNIQUE  INDEX  index2_id ( id  ASC)  
  5. ); 

运行结果显示创建成功,使用SHOW CREATE TABLE语句查看表的结构。显示如下:

 
 
  1. mysql> SHOW CREATE TABLE index2 \G  
  2. *************************** 1. row **************************
  3.        Table: index2  
  4. Create Table: CREATE TABLE `index2` (  
  5.   `id` int(11) DEFAULT NULL,  
  6.   `name` varchar(20) DEFAULT NULL,  
  7.   UNIQUE KEY `id` (`id`),  
  8.   UNIQUE KEY `index2_id` (`id`)  
  9. ENGINE=InnoDB DEFAULT CHARSET=utf8 
  10. 1 row in set (0.00 sec) 

结果可以看到,id字段上已经建立了一个名为index2_id的唯一性索引。这里的id字段可以没有进行唯一性约束,也可以在该字段上成功创建唯一性索引。但是,这样可能达不到提高查询速度的目的。

7.2.1  创建表的时候创建索引(2)

3.创建全文索引

全文索引只能创建在CHAR、VARCHAR或TEXT类型的字段上。而且,现在只有MyISAM存储引擎支持全文索引。

【示例7-3】 下面创建一个表名为index3的表,在表中的info字段上建立名为index3_ info的全文索引。SQL代码如下:

 
 
  1. CREATE  TABLE  index3 (
  2. id    INT  ,  
  3. info   VARCHAR(20) ,  
  4. FULLTEXT  INDEX  index3_info ( info )  
  5. )ENGINE=MyISAM

运行结果显示创建成功,使用SHOW CREATE TABLE语句查看表的结构。显示如下:

 
 
  1. mysql> SHOW CREATE TABLE index3 \G  
  2. *************************** 1. row ************************* 
  3.        Table: index3  
  4. Create Table: CREATE TABLE `index3` (  
  5.   `id` int(11) DEFAULT NULL,  
  6.   `info` varchar(20) DEFAULT NULL,  
  7.   FULLTEXT KEY `index3_info` (`info`)  
  8. ENGINE=MyISAM DEFAULT CHARSET=utf8 
  9. 1 row in set (0.00 sec) 

结果可以看到,info字段上已经建立了一个名为index3_info的全文索引。如果表的存储引擎不是MyISAM存储引擎,系统会提示"ERROR 1214 (HY000): The used table type doesn't support FULLTEXT indexes"。

注意:目前只有MyISAM存储引擎支持全文索引,InnoDB存储引擎还不支持全文索引。因此,在创建全文索引时一定注意表的存储引擎的类型(MyISAM存储引擎)。对于经常需要索引的字符串、文字数据等信息,可以考虑存储到MyISAM存储引擎的表中。

4.创建单列索引

单列索引是在表的单个字段上创建索引

【示例7-4】 下面创建一个表名为index4的表,在表中的subject字段上建立名为index4_st的单列索引。SQL代码如下:

 
 
  1. CREATE  TABLE  index4 (
  2. id    INT  ,  
  3. subject   VARCHAR(30) ,  
  4. INDEX  index4_st ( subject(10) )  
  5. ); 

运行结果显示创建成功,使用SHOW CREATE TABLE语句查看表的结构。显示如下:

 
 
  1. mysql> SHOW CREATE TABLE index4 \G  
  2. *************************** 1. row **************************
  3.        Table: index4  
  4. Create Table: CREATE TABLE `index4` (  
  5.   `id` int(11) DEFAULT NULL,  
  6.   `subject` varchar(30) DEFAULT NULL,  
  7.   KEY `index4_st` (`subject`(10))  
  8. ENGINE=InnoDB DEFAULT CHARSET=utf8 
  9. 1 row in set (0.00 sec) 

结果可以看到,subject字段上已经建立了一个名为index4_st的单列索引。细心的读者可能会发现,subject字段长度为30,而index4_st索引的长度只有10。这样做的目的还是为了提高查询速度。对于字符型的数据,可以不用查询全部信息,而只查询其前面的若干字符信息。

5.创建多列索引

创建多列索引是在表的多个字段上创建一个索引。

【示例7-5】 下面创建一个表名为index5的表,在表中的name和sex字段上建立名为index5_ns的多列索引。SQL代码如下:

 
 
  1. CREATE  TABLE  index5 (
  2. id  INT  ,  
  3. name   VARCHAR(20) ,  
  4. sex   CHAR(4) ,  
  5. INDEX  index5_ns ( name, sex )  
  6. ); 

运行结果显示创建成功,使用SHOW CREATE TABLE语句查看表的结构。显示如下:

 
 
  1. mysql> SHOW CREATE TABLE index5 \G  
  2. *************************** 1. row *************************
  3.        Table: index5  
  4. Create Table: CREATE TABLE `index5` (  
  5.   `id` int(11) DEFAULT NULL,  
  6.   `name` varchar(20) DEFAULT NULL,  
  7.   `sex` char(4) DEFAULT NULL,  
  8.   KEY `index5_ns` (`name`,`sex`)  
  9. ENGINE=InnoDB DEFAULT CHARSET=utf8 
  10. 1 row in set (0.00 sec) 

结果可以看到,name和sex字段上已经建立了一个名为index5_ns的多列索引。多列索引中,只有查询条件中使用了这些字段中第一个字段时,索引才会被使用。(最左前缀原则)用EXPLAIN语句可以查看索引的使用情况。如果只是有name字段作为查询条件进行查询,显示结果如下:

 
 
  1. mysql> EXPLAIN select * from index5 where name='hjh' \G  
  2. *************************** 1. row **************************
  3.            id: 1  
  4.   select_type: SIMPLE  
  5.         table: index5  
  6.          type: ref  
  7. possible_keys: index5_ns  
  8.           key: index5_ns  
  9.       key_len: 83  
  10.           ref: const  
  11.          rows: 1  
  12.         Extra: Using index condition  
  13. 1 row in set (0.00 sec) 

结果显示,possible_keys和key的值都是index5_ns。这说明使用name字段进行索引时,索引index5_ns已经被使用。如果只使用sex字段作为查询条件进行查询,显示结果如下:

 
 
  1. mysql> EXPLAIN select * from index5 where sex='n' \G  
  2. *************************** 1. row **************************
  3.            id: 1  
  4.   select_type: SIMPLE  
  5.         table: index5  
  6.          type: ALL  
  7. possible_keys: NULL  
  8.           key: NULL  
  9.       key_len: NULL  
  10.           ref: NULL  
  11.          rows: 1  
  12.         Extra: Using where  
  13. 1 row in set (0.00 sec) 

此时的结果显示,possible_keys和key的值都为NULL。额外信息(Extra)显示正在使用Where条件查询,而未使用索引。

技巧:使用多列索引时一定要特别注意,只有使用了索引中的第一个字段时才会触发索引。如果没有使用索引中的第一个字段,那么这个多列索引就不会起作用。因此,在优化查询速度时,可以考虑优化多列索引。

6.创建空间索引

创建空间索引时必须使用SPATIAL参数来设置。创建空间索引时,表的存储引擎必须是MyISAM类型。而且,索引字段必须有非空约束。

【示例7-6】 下面创建一个表名为index6的表,在表中的space字段上建立名为index6_sp的空间索引。SQL代码如下:

 
 
  1. CREATE  TABLE  index6 (
  2. id  INT  ,  
  3. space  GEOMETRY  NOT NULL,  
  4. SPATIAL  INDEX  index6_sp (space )  
  5. )ENGINE=MyISAM

运行结果显示创建成功,使用SHOW CREATE TABLE语句查看表的结构。显示如下:

 
 
  1. mysql> SHOW CREATE TABLE index6 \G  
  2. *************************** 1. row **************************
  3.        Table: index6  
  4. Create Table: CREATE TABLE `index6` (  
  5.   `id` int(11) DEFAULT NULL,  
  6.   `space` geometry NOT NULL,  
  7.   SPATIAL KEY `index6_sp` (`space`)  
  8. ENGINE=MyISAM DEFAULT CHARSET=utf8 
  9. 1 row in set (0.00 sec) 

结果可以看到,space字段上已经建立了一个名为index6_sp的空间索引。值得注意的是,space字段是非空的,而且数据类型是GEOMETRY类型。这个类型是空间数据类型。空间类型包括GEOMETRY、POINT、LINESTRING和POLYGON类型等。这些空间数据类型平时很少用到。

-----------------------------------------------------------

7.2.2  在已经存在的表上创建索引-----------------------------------------------------------

在已经存在的表中,可以直接为表上的一个或几个字段创建索引。基本形式如下:

 
 
  1. CREATE  [ UNIQUE | FULLTEXT | SPATIAL ]  INDEX  索引名  
  2.  ON  表名  (属性名  [ (长度) ]  [  ASC | DESC] ); 

其中,UNIQUE是可选参数,表示索引为唯一性索引;FULLTEXT是可选参数,表示索引为全文索引;SPATIAL也是可选参数,表示索引为空间索引;"INDEX"参数用来指定字段为索引的;"索引名"参数是给创建的索引取的新名称;"表名"参数是指需要创建索引的表的名称,该表必须是已经存在的,如果不存在,需要先创建;"属性名"参数指定索引对应的字段的名称,该字段必须为前面定义好的字段;"长度"是可选参数,其指索引的长度,必须是字符串类型才可以使用;ASC和DESC都是可选参数,ASC参数表示升序排列,DESC参数表示降序排列。

1.创建普通索引

【示例7-7】 下面在example0表中的id字段上建立名为index7_id的索引。SQL代码如下:

 
 
  1. CREATE  INDEX  index7_id  ON  example0 ( id ) ; 

在创建索引之前,先使用SHOW CREATE TABLE语句查看example0表的结构,显示如下:

 
 
  1. mysql> SHOW CREATE TABLE example0 \G  
  2. *************************** 1. row **************************
  3.        Table: example0  
  4. Create Table: CREATE TABLE `example0` (  
  5.   `id` int(11) DEFAULT NULL,  
  6.   `name` varchar(20) DEFAULT NULL,  
  7.   `sex` tinyint(1) DEFAULT NULL  
  8. ENGINE=InnoDB DEFAULT CHARSET=utf8 
  9. 1 row in set (0.08 sec) 

查询结果显示,example0表还没有索引。下面使用CREATE INDEX语句创建索引。CREATE INDEX语句执行结果如下:

 
 
  1. mysql> CREATE  INDEX  index7_id  ON  example0 ( id ) ;  
  2. Query OK, 0 rows affected (0.06 sec)  
  3. Records: 0  Duplicates: 0  Warnings: 0 

运行结果显示创建成功,使用SHOW CREATE TABLE语句查看表的结构。显示如下:

 
 
  1. mysql> SHOW CREATE TABLE example0 \G  
  2. *************************** 1. row **************************  
  3.        Table: example0  
  4. Create Table: CREATE TABLE `example0` (  
  5.   `id` int(11) DEFAULT NULL,  
  6.   `name` varchar(20) DEFAULT NULL,  
  7.   `sex` tinyint(1) DEFAULT NULL,  
  8.   KEY `index7_id` (`id`)  
  9. ENGINE=InnoDB DEFAULT CHARSET=utf8 
  10. 1 row in set (0.00 sec) 

结果可以看到,example0表中的id字段上已经创建了一个名为index7_id的索引。这表示使用CREATE INDEX语句成功的在example0表上创建了普通索引。

2.创建唯一性索引

【示例7-8】 下面在index8表中的course_id字段上建立名为index8_id的唯一性索引。SQL代码如下:

CREATE  UNIQUE  INDEX  index8_id  ON  index8( course_id ) ;

其中,index8_id为索引的名词;UNIQUE用来设置索引为唯一性索引;表index8中的course_id字段可以有唯一性约束,也可以没有唯一性约束。

3.创建全文索引

【示例7-9】 下面在index9表中的info字段上建立名为index9_info的全文索引。SQL代码如下:

 
 
  1. CREATE  FULLTEXT  INDEX  index9_info  ON  index9( info ) ; 

其中,FULLTEXT用来设置索引为全文索引;表index9的存储引擎必须是MyISAM类型;info字段必须为CHAR、VARCHAR和TEXT等类型。

4.创建单列索引

【示例7-10】 下面在index10表中的address字段上建立名为index10_addr的单列索引。address字段的数据类型为VARCHAR(20),索引的数据类型为CHAR(4)。SQL代码如下:

 
 
  1. CREATE  INDEX  index10_addr  ON  index10( address(4) ) ; 

这样,查询时可以只查询address字段的前4个字符,而不需要全部查询。

5.创建多列索引

【示例7-11】 下面在index11表中的name和address字段上建立名为index11_na的多列索引。SQL代码如下:

 
 
  1. CREATE  INDEX  index11_na  ON  index11( name, address ) ; 

该索引创建好了以后,查询条件中必须有name字段才能使用索引。

6.创建空间索引

【示例7-12】 下面在index12表中的line字段上建立名为index12_line的多列索引。SQL代码如下:

 
 
  1. CREATE  SPATIAL  INDEX  index12_line  ON  index12( line ) ; 
其中,SPATIAL用来设置索引为空间索引;表index12的存储引擎必须是MyISAM类型;line字段必须为空间数据类型,而且是非空的。

-----------------------------------------------------------

7.2.3  用ALTER TABLE语句来创建索引

在已经存在的表上,可以通过ALTER TABLE语句直接为表上的一个或几个字段创建索引。基本形式如下:

 
 
  1. ALTER  TABLE  表名  ADD   [ UNIQUE | FULLTEXT | SPATIAL ]   
  2. INDEX  
  3. 索引名(属性名  [ (长度) ]  [ ASC | DESC]); 

其中的参数与上面的两种方式的参数是一样的。

1.创建普通索引

【示例7-13】 下面在example0表中的name字段上建立名为index13_name的索引。SQL代码如下:

 
 
  1. ALTER  TABLE  example0  ADD  INDEX  index13_name ( name(20) ; 

使用ALTER TABLE语句创建索引之前,先执行SHOW CREATE TABLE语句查看example0表的结构。SHOW CREATE TABLE语句执行结果如下:

 
 
  1. mysql> SHOW CREATE TABLE example0 \G  
  2. *************************** 1. row **************************
  3.        Table: example0  
  4. Create Table: CREATE TABLE `example0` (  
  5.   `id` int(11) DEFAULT NULL,  
  6.   `name` varchar(20) DEFAULT NULL,  
  7.   `sex` tinyint(1) DEFAULT NULL,  
  8.   KEY `index7_id` (`id`)  
  9. ENGINE=InnoDB DEFAULT CHARSET=utf8 
  10. 1 row in set (0.00 sec) 

结果显示,example0表上只有index7_id索引。下面执行ALTER TABLE语句创建index13_name索引。ALTER TABLE语句执行结果如下:

 
 
  1.  ALTER TABLE example0 ADD INDEX index13_name ( name(20) ) ;  
  2. Query OK, 0 rows affected (0.01 sec)  
  3. Records: 0  Duplicates: 0  Warnings: 0 

运行结果显示创建成功,使用SHOW CREATE TABLE语句查看example0表的结构。显示如下:

 
 
  1. mysql> SHOW CREATE TABLE example0 \G  
  2. *************************** 1. row **************************
  3.        Table: example0  
  4. Create Table: CREATE TABLE `example0` (  
  5.   `id` int(11) DEFAULT NULL,  
  6.   `name` varchar(20) DEFAULT NULL,  
  7.   `sex` tinyint(1) DEFAULT NULL,  
  8.   KEY `index7_id` (`id`),  
  9.   KEY `index13_name` (`name`)  
  10. ENGINE=InnoDB DEFAULT CHARSET=utf8 
  11. 1 row in set (0.00 sec) 

结果可以看到,name字段已经创建了一个名为index13_name的索引。

2.创建唯一性索引

【示例7-14】 下面在index14表中的course_id字段上,建立名为index14_id的唯一性索引。SQL代码如下:

 
 
  1. ALTER  TABLE  index14  ADD  UNIQUE  INDEX  index14_id ( course_id ) ; 

其中,index14_id为索引的名词;UNIQUE用来设置索引为唯一性索引;表index14中的course_id字段可以有唯一性约束,也可以没有唯一性约束。

3.创建全文索引

【示例7-15】 下面在index15表中的info字段上建立名为index15_info的全文索引。SQL代码如下:

 
 
  1. ALTER  TABLE  index15  ADD  FULLTEXT  INDEX  index15_info ( info ) ; 

其中,FULLTEXT用来设置索引为全文索引;表index15的存储引擎必须是MyISAM类型;info字段必须为CHAR、VARCHAR和TEXT等类型。

4.创建单列索引

【示例7-16】 下面在index16表中的address字段上建立名为index16_addr的单列索引。address字段的数据类型为VARCHAR(20),索引的数据类型为CHAR(4)。SQL代码如下:

 
 
  1. ALTER TABLE  index16 ADD INDEX index16_addr( address(4) ) ; 

这样,查询时可以只查询address字段的前4个字符,而不需要全部查询。

5.创建多列索引

【示例7-17】 下面在index17表中的name和address字段上建立名为index17_na的多列索引。SQL代码如下:

 
 
  1. ALTER TABLE index17 ADD INDEX  index17_na( name, address ) ; 

该索引创建好了以后,查询条件中必须有name字段才能使用索引。

6.创建空间索引

【示例7-18】 下面在index18表中的line字段上建立名为index18_line的多列索引。SQL代码如下:

 
 
  1. ALTER TABLE index18 ADD SPATIAL INDEX  index18_line( line ) ; 

其中,SPATIAL用来设置索引为空间索引;表index18的存储引擎必须是MyISAM类型;line字段必须是非空的,而且必须是空间数据类型。

-----------------------------------------------------------

7.3  删除索引

删除索引是指将表中已经存在的索引删除掉。一些不再使用的索引会降低表的更新速度,影响数据库的性能。对于这样的索引,应该将其删除。

对应已经存在的索引,可以通过DROP语句来删除索引。基本形式如下:

 
 
  1. DROP  INDEX  索引名  ON  表名 ; 

其中,"索引名"参数指要删除的索引的名称;"表名"参数指索引所在的表的名称。

【示例7-19】 下面删除index1表的索引。在删除索引之前,使用SHOW CREATE TABLE语句来查看索引的名称。SHOW CREATE TABLE语句执行如下:

 
 
  1. mysql> SHOW CREATE TABLE index1 \G  
  2. *************************** 1. row **************************
  3.        Table: index1  
  4. Create Table: CREATE TABLE `index1` (  
  5.   `id` int(11) DEFAULT NULL,  
  6.   `name` varchar(20) DEFAULT NULL,  
  7.   `sex` tinyint(1) DEFAULT NULL,  
  8.   KEY `id` (`id`)  
  9. ENGINE=InnoDB DEFAULT CHARSET=utf8 
  10. 1 row in set (0.00 sec) 

结果显示,索引的名称为id。然后执行DROP语句来删除索引。SQL代码如下:

 
 
  1. DROP  INDEX  id  ON  index1 ; 

代码执行结果如下:

 
 
  1. mysql> DROP  INDEX  id  ON  index1 ;  
  2. Query OK, 0 rows affected (0.02 sec)  
  3. Records: 0  Duplicates: 0  Warnings: 0 

结果显示索引删除成功。为了确认索引是否已经成功删除,再次执行SHOW CREATE TABLE语句来查看index1表的结构。SHOW CREATE TABLE语句执行如下:

 
 
  1. mysql> SHOW CREATE TABLE index1 \G  
  2. *************************** 1. row **************************
  3.        Table: index1  
  4. Create Table: CREATE TABLE `index1` (  
  5.   `id` int(11) DEFAULT NULL,  
  6.   `name` varchar(20) DEFAULT NULL,  
  7.   `sex` tinyint(1) DEFAULT NULL  
  8. ENGINE=InnoDB DEFAULT CHARSET=utf8 
  9. 1 row in set (0.00 sec) 

结果显示,名为id的索引已经不存在了。

-----------------------------------------------------------

在本小节将在job数据库中创建一个user表和一个information表。具体如表7.1和表7.2所示。

表7.1  user表的内容

字段名

字段描述

数据类型

主键

外键

非空

唯一

自增

userid

编号

INT(10)

username

用户名

VARCHAR(20)

passwd

密码

VARCHAR(20)

info

附加信息

TEXT

表7.2  information表的内容

字段名

字段描述

数据类型

主键

外键

非空

唯一

自增

id

编号

INT(10)

name

姓名

VARCHAR(20)

sex

性别

VARCHAR(4)

birthday

出生日期

DATE

address

家庭住址

VARCHAR(50)

tel

电话号码

VARCHAR(20)

pic

照片

BLOB

按照下列要求进行操作:

(1)登录数据库系统后创建job数据库。

(2)创建user表。存储引擎为MyISAM类型。创建表的时候同时几个索引,在userid字段上创建名为index_uid的唯一性索引,并且以降序的形式排列;在username和passwd字段上创建名为index_user的多列索引;在info字段上创建名为index_info的全文索引。

(3)创建information表。

(4)在name字段创建名为index_name的单列索引,索引长度为10。

(5)在birthday和address字段是创建名为index_bir的多列索引,然后判断索引的使用情况。

(6)用ALTER TABLE语句在id字段上创建名为index_id的唯一性索引,而且以升序排列。

(7)删除user表上的index_user索引。

(8)删除information表上的index_name索引。

本实例的执行过程如下:

1.登录数据库系统并创建job数据库

在命令行中登录MySQL数据库管理系统,输入内容如下:

 
 
  1. mysql -h localhost -u root -p 

提示输入密码后,按要求输入密码,显示为:

 
 
  1. Enter password: **** 

按Enter键后,检验密码正确后进入MySQL管理系统。执行SHOW语句来查看数据库系统中已经存在的数据库,代码执行如下:

 
 
  1. mysql> SHOW DATABASES;  
  2. +----------------------------+  
  3. | Database           |  
  4. +----------------------------+  
  5. | information_schema |  
  6. | example           |  
  7. | mysql              |  
  8. | school             |  
  9. | test                |  
  10. +----------------------------+  
  11. 6 rows in set (0.08 sec) 

结果显示,数据库系统中不存在名为job的数据库。执行CREATE DATABASE语句来创建数据库,代码执行如下:

 
 
  1. mysql> CREATE DATABASE job;  
  2. Query OK, 1 row affected (0.08 sec) 

执行结果显示,数据库创建成功。再次执行SHOW语句来查看job数据库是否已经存在。代码执行如下:

 
 
  1. mysql> SHOW DATABASES;  
  2. +---------------------------+  
  3. | Database          |  
  4. +---------------------------+  
  5. | information_schema |  
  6. | example           |  
  7. | job                |  
  8. | mysql             |  
  9. | school             |  
  10. | test               |  
  11. +---------------------------+  
  12. 7 rows in set (0.00 sec) 

结果显示,已经存在名为job的数据库。

2.创建user表

先使用USE语句选择job数据库。代码执行如下:

 
 
  1. mysql> USE job;  
  2. Database changed 

结果显示,数据库已经选择成功。然后可以执行CREATE TABLE语句来创建user表。根据实例要求,存储引擎为MyISAM类型;在userid字段上创建名为index_uid的唯一性索引,并且以降序的形式排列;在username和passwd字段上创建名为index_user的多列索引;在info字段上创建名为index_info的全文索引。SQL代码如下:

 
 
  1. CREATE  TABLE  user( 
  2. userid INT(10) NOT NULL UNIQUE PRIMARY KEY  AUTO_INCREMENT ,
  3. username  VARCHAR(20)  NOT NULL ,  
  4. passwd  VARCHAR(20)  NOT NULL ,  
  5. info  TEXT ,  
  6. UNIQUE  INDEX  index_uid ( userid  DESC ) ,  
  7. INDEX  index_user ( username, passwd ) ,  
  8. FULLTEXT  INDEX  index_info( info )  
  9. ENGINE=MyISAM ; 

执行结果显示,user表创建成功。执行SHOW CREATE TABLE语句来查看use表的结构。执行结果如下:

 
 
  1. mysql> SHOW CREATE TABLE user \G  
  2. *************************** 1. row **************************
  3.        Table: user  
  4. Create Table: CREATE TABLE `user` (  
  5.   `userid` int(10) NOT NULL AUTO_INCREMENT,  
  6.   `username` varchar(20) NOT NULL,  
  7.   `passwd` varchar(20) NOT NULL,  
  8.   `info` text,  
  9.   PRIMARY KEY (`userid`),  
  10.   UNIQUE KEY `userid` (`userid`),  
  11.   UNIQUE KEY `index_uid` (`userid`),  
  12.   KEY `index_user` (`username`,`passwd`),  
  13.   FULLTEXT KEY `index_info` (`info`)  
  14. ENGINE=MyISAM DEFAULT CHARSET=utf8 
  15. 1 row in set (0.00 sec)  

结果显示,index_uid是userid字段上的唯一性索引;index_user是user字段和passwd字段上的索引;index_info是info字段上的全文索引;存储引擎为MyISAM。

3.创建information表

在job数据库下创建名为information的表。代码如下:

 
 
  1. CREATE TABLE information ( 
  2. id  INT(10)  NOT NULL  UNIQUE  PRIMARY KEY  AUTO_INCREMENT,  
  3. name  VARCHAR(20)  NOT NULL ,  
  4. sex  VARCHAR(4)  NOT NULL ,  
  5. birthday  DATE ,  
  6. address  VARCHAR(50) ,  
  7. tel  VARCHAR(20) ,  
  8. pic  BLOB  
  9. ); 

执行结果显示,information表创建成功。执行SHOW CREATE TABLE语句来查看information表的结构。执行结果如下:

 
 
  1. mysql> SHOW CREATE TABLE information \G  
  2. *************************** 1. row **************************
  3.        Table: information  
  4. Create Table: CREATE TABLE `information` (  
  5.   `id` int(10) NOT NULL AUTO_INCREMENT,  
  6.   `name` varchar(20) NOT NULL,  
  7.   `sex` varchar(4) NOT NULL,  
  8.   `birthday` date DEFAULT NULL,  
  9.   `address` varchar(50) DEFAULT NULL,  
  10.   `tel` varchar(20) DEFAULT NULL,  
  11.   `pic` blob,  
  12.   PRIMARY KEY (`id`),  
  13.   UNIQUE KEY `id` (`id`)  
  14. ENGINE=InnoDB DEFAULT CHARSET=utf8 
  15. 1 row in set (0.00 sec) 

查询结果显示,id字段是主键,而且有唯一性约束。

4.在name字段创建名为index_name的索引

使用CREATE INDEX语句创建index_name索引CREATE  INDEX  index_name  ON  information( name(10) )。代码执行如下:

 
 
  1. mysql> CREATE  INDEX  index_name  ON  information( name(10) ) ;  
  2. Query OK, 0 rows affected (0.02 sec)  
  3. Records: 0  Duplicates: 0  Warnings: 0  

结果显示index_name索引创建成功。

5.创建名为index_bir的多列索引

使用CREATE INDEX语句创建index_bir索引。代码执行如下:

 
 
  1. mysql> CREATE  INDEX  index_bir  ON  information(birthday, address ) ;  
  2. Query OK, 0 rows affected (0.02 sec)  
  3. Records: 0  Duplicates: 0  Warnings: 0 

结果显示,index_bir索引创建成功。

6.用ALTER TABLE语句创建名为index_id的唯一性索引

使用ALTER TABLE语句创建index_id索引。代码执行如下:

 
 
  1. mysql> ALTER  TABLE  information  ADD  INDEX  index_id( id  ASC ) ;  
  2. Query OK, 0 rows affected (0.02 sec)  
  3. Records: 0  Duplicates: 0  Warnings: 0 

结果显示index_id索引创建成功。执行SHOW CREATE TABLE语句来查看information表的结构。执行结果如下:

 
 
  1. mysql> SHOW CREATE TABLE information \G  
  2. *************************** 1. row **************************
  3.        Table: information  
  4. Create Table: CREATE TABLE `information` (  
  5.   `id` int(10) NOT NULL AUTO_INCREMENT,  
  6.   `name` varchar(20) NOT NULL,  
  7.   `sex` varchar(4) NOT NULL,  
  8.   `birthday` datetime DEFAULT NULL,  
  9.   `address` varchar(50) DEFAULT NULL,  
  10.   `tel` varchar(20) DEFAULT NULL,  
  11.   `pic` blob,  
  12.   PRIMARY KEY (`id`),  
  13.   UNIQUE KEY `id` (`id`),  
  14.   KEY `index_name` (`name`(10)),  
  15.   KEY `index_bir` (`birthday`,`address`),  
  16.   KEY `index_id` (`id`)  
  17. ENGINE=InnoDB DEFAULT CHARSET=utf8 
  18. 1 row in set (0.00 sec) 

执行结果显示,information表中已经存在index_name、index_bir和index_id等3个索引。

7.删除user表上的index_user索引

执行DROP语句可以删除user表上的索引。代码执行结果如下:

 
 
  1. mysql> DROP INDEX index_user ON user;  
  2. Query OK, 0 rows affected (0.14 sec)  
  3. Records: 0  Duplicates: 0  Warnings: 0 

结果显示删除成功。执行SHOW CREATE TABLE语句来查看user表的结构。执行结果如下:

 
 
  1. mysql> SHOW CREATE TABLE user \G  
  2. *************************** 1. row **************************
  3.        Table: user  
  4. Create Table: CREATE TABLE `user` (  
  5.   `userid` int(10) NOT NULL AUTO_INCREMENT,  
  6.   `username` varchar(20) NOT NULL,  
  7.   `passwd` varchar(20) NOT NULL,  
  8.   `info` text,  
  9.   PRIMARY KEY (`userid`),  
  10.   UNIQUE KEY `userid` (`userid`),  
  11.   UNIQUE KEY `index_uid` (`userid`),  
  12.   FULLTEXT KEY `index_info` (`info`)  
  13. ENGINE=MyISAM DEFAULT CHARSET=utf8 
  14. 1 row in set (0.00 sec) 

结果显示,index_user索引已经不存在了。

8.删除information表上的index_name索引

执行DROP语句可以删除information表上的index_name索引。代码执行结果如下:

  
  
  1. mysql> DROP INDEX index_name ON information ;  
  2. Query OK, 0 rows affected (0.03 sec)  
  3. Records: 0  Duplicates: 0  Warnings: 0 

结果显示删除成功。执行SHOW CREATE TABLE语句来查看information表的结构。执行结果如下:

  
  
  1. mysql> SHOW CREATE TABLE information \G  
  2. *************************** 1. row **************************
  3.        Table: information  
  4. Create Table: CREATE TABLE `information` (  
  5.   `id` int(10) NOT NULL AUTO_INCREMENT,  
  6.   `name` varchar(20) NOT NULL,  
  7.   `sex` varchar(4) NOT NULL,  
  8.   `birthday` datetime DEFAULT NULL,  
  9.   `address` varchar(50) DEFAULT NULL,  
  10.   `tel` varchar(20) DEFAULT NULL,  
  11.   `pic` blob,  
  12.   PRIMARY KEY (`id`),  
  13.   UNIQUE KEY `id` (`id`),  
  14.   KEY `index_bir` (`birthday`,`address`),  
  15.   KEY `index_id` (`id`)  
  16. ENGINE=InnoDB DEFAULT CHARSET=utf8 
  17. 1 row in set (0.00 sec) 

结果显示,index_name索引已经不存在了。

-------------------------------------------------------

上机实践

题目要求:

(1)在数据库job下创建workInfo表。创建表的同时在id字段上创建名为index_id的唯一性索引,而且以降序的格式排列。workInfo表内容如表7.3所示。

表7.3  workInfo表的内容

字段名

字段描述

数据类型

主键

外键

非空

唯一

自增

id

编号

INT(10)

name

职位名称

VARCHAR(20)

type

职位类别

VARCHAR(10)

address

工作地址

VARCHAR(50)

wages

工资

INT

contents

工作内容

TINYTEXT

extra

附加信息

TEXT


(2)使用CREATE INDEX语句为name字段创建长度为10的索引index_name。

(3)使用ALTER TABLE语句在type和address上创建名为index_t的索引。

(4)将workInfo表的存储引擎更改为MyISAM类型。

(5)使用ALTER TABLE语句在extra字段上创建名为index_ext的全文索引。

(6)删除workInfo表的唯一性索引index_id。

操作如下:

(1)先查看是否存在job数据库。如果存在,用USE语句选择job数据库。如果不存在,用CREATE DATABASE语句创建该数据库。然后,用CREATE TABLE语句创建workInfo表,SQL代码如下:

   
   
  1. CREATE  TABLE  workInfo (
  2.  id  INT(10)  NOT NULL  UNIQUE  PRIMARY KEY  AUTO_INCREMENT,  
  3. name  VARCHAR(20)  NOT NULL ,  
  4. type  VARCHAR(10) ,  
  5. address  VARCHAR(50) ,  
  6. tel  VARCHAR(20) ,  
  7. wages  INT ,  
  8. contents  TINYTEXT ,  
  9. extra  TEXT ,  
  10. UNIQUE  INDEX  index_id (id  DESC)  
  11. ); 

(2)使用CREATE INDEX语句为name字段创建长度为10的索引index_name。代码如下:

   
   
  1. CREATE  INDEX  index_name  ON  workInfo( name(10) ) ; 

(3)使用ALTER TABLE语句在type和address上创建名为index_t的索引。代码如下:

   
   
  1. ALTER  TABLE  workInfo  ADD  INDEX  index_t( type, address ) ; 

(4)使用ALTER TABLE语句将workInfo表的存储引擎更改为MyISAM类型。代码如下:

   
   
  1. ALTER  TABLE  workInfo  ENGINE=MyISAM

(5)使用ALTER TABLE语句在extra字段上创建名为index_ext的全文索引。代码如下:

   
   
  1. ALTER  TABLE  workInfo  ADD  FULLTEXT  INDEX  index_ext (extra ) ; 

(6)使用DROP语句删除workInfo表的唯一性索引index_id。代码如下:

   
   
  1. DROP  INDEX index_id  ON  workInfo ;. 

-------------------------------------------------------

7.6  常见问题及解答

1.MySQL中索引、主键和唯一性的区别是什么?

索引建立在一个或者几个字段上。建立了索引后,表中的数据就按照索引的一定规则排列。这样可以提高查询速度。

主键是表中数据的唯一标识。不同的记录的主键值不同。例如,身份证好比主键,每个身份证号都可以唯一的确定一个人。在建立主键时,系统会自动建立一个唯一性索引。

唯一性也是建立在表中一个或者几个字段上。其目的是为了对于不同的记录,具有唯一性的字段的值是不同的。

2.表中建立了索引以后,导入大量数据为什么会很慢?

对已经建立了索引的表中插入数据时,插入一条数据就要对该记录按索引排序。因此,导入大量数据的时候速度会很慢。解决这种情况的办法是,在没有任何索引的情况插入数据,然后建立索引。

-------------------------------------------------------

小结

本章介绍了MySQL数据库的索引的基础知识、创建索引的方法和删除索引的方法。创建索引的内容是本章的重点。应该重点掌握创建索引的3种方法。这3种方法分别是创建表的时候创建索引、使用CREATE INDEX语句来创建索引和使用ALTER TABLE语句来创建索引。设计索引的基本原则是本章的难点。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值