大数据兼云计算(王明龙)讲师-MYSQL-DAY11-索引

**

索引

**


索引简介

所有MySQL列类型可以被索引。根据存储引擎定义每个表的最大索引数和最大索引长度。
所有存储引擎支持每个表至少16个索引,总索引长度至少为256字节。大多数存储引擎有更高的限制。

索引的存储类型目前只有两种(btree和hash),具体和存储引擎模式相关:
MyISAM        btree
InnoDB        btree
MEMORY/Heap   hash,btree
默认情况MEMORY/Heap存储引擎使用hash索引

MySQL的btree索引和hash索引的区别
hash 索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像btree(B-Tree)索引需要从根节点到枝节点,
最后才能访问到页节点这样多次的IO访问,所以 hash 索引的查询效率要远高于 btree(B-Tree) 索引。

一. hash-索引

虽然 hash 索引效率高,但是 hash 索引本身由于其特殊性也带来了很多限制和弊端,主要有以下这些:

1.hash 索引仅仅能满足=,<=>,INIS NULL或者IS NOT NULL查询,不能使用范围查询。
由于 hash 索引比较的是进行 hash 运算之后的 hash 值,所以它只能用于等值的过滤,不能用于基于范围的过滤,因为经
过相应的 hash 算法处理之后的 hash 值的大小关系,并不能保证和hash运算前完全一样。

2.hash 索引无法被用来避免数据的排序操作。
由于 hash 索引中存放的是经过 hash 计算之后的 hash 值,而且hash值的大小关系并不一定和 hash 运算前的键值完全一
样,所以数据库无法利用索引的数据来避免任何排序运算;

3.hash 索引不能利用部分索引键查询。
对于组合索引,hash 索引在计算 hash 值的时候是组合索引键合并后再一起计算 hash 值,而不是单独计算 hash 值,所以
通过组合索引的前面一个或几个索引键进行查询的时候,hash 索引也无法被利用。

4.hash 索引在任何时候都不能避免表扫描。
前面已经知道,hash 索引是将索引键通过 hash 运算之后,将 hash运算结果的 hash 值和所对应的行指针信息存放于一个hash
表中,由于不同索引键存在相同 hash 值,所以即使取满足某个 hash 键值的数据的记录条数,也无法从 hash 索引中直接完成
查询,还是要通过访问表中的实际数据进行相应的比较,并得到相应的结果。

5.hash 索引遇到大量hash值相等的情况后性能并不一定就会比B-Tree索引高。
对于选择性比较低的索引键,如果创建 hash 索引,那么将会存在大量记录指针信息存于同一个 hash 值相关联。这样要定位
某一条记录时就会非常麻烦,会浪费多次表数据的访问,而造成整体性能低下


二. B-Tree-索引
    B-Tree 索引是 MySQL 数据库中使用最为频繁的索引类型,除了 Archive 存储引擎之外的其他所有的存储引擎都支持 B-Tree 
索引。不仅仅在 MySQL 中是如此,实际上在其他的很多数据库管理系统中B-Tree 索引也同样是作为最主要的索引类型,这主要是
因为 B-Tree 索引的存储结构在数据库的数据检索中有非常优异的表现。

    一般来说, MySQL 中的 B-Tree 索引的物理文件大多都是以 Balance Tree 的结构来存储的,也就是所有实际需要的数据都存
放于 Tree 的 Leaf Node ,而且到任何一个 Leaf Node 的最短路径的长度都是完全相同的,所以我们大家都称之为 B-Tree 索引当
然,可能各种数据库(或 MySQL 的各种存储引擎)在存放自己的 B-Tree 索引的时候会对存储结构稍作改造。

    如 Innodb 存储引擎的 B-Tree 索引实际使用的存储结构实际上是 B+Tree ,也就是在 B-Tree 数据结构的基础上做了很小的改
造,在每一个Leaf Node 上面出了存放索引键的相关信息之外,还存储了指向与该 Leaf Node 相邻的后一个 LeafNode 的指针信息,
这主要是为了加快检索多个相邻 Leaf Node 的效率考虑。 

    在 Innodb 存储引擎中,存在两种不同形式的索引,一种是 Cluster 形式的主键索引( Primary Key ),另外一种则是和其他
存储引擎(如 MyISAM 存储引擎)存放形式基本相同的普通 B-Tree 索引,这种索引在 Innodb 存储引擎中被称为 Secondary Index 。

    在 Innodb 中如果通过主键来访问数据效率是非常高的,而如果是通过Secondary Index来访问数据的话,Innodb 首先通过Secondary Index 的相关信息,
通过相应的索引键检索到 Leaf Node之后,需要再通过 Leaf Node 中存放的主键值再通过主键索引来获取相应的数据行。

    MyISAM 存储引擎的主键索引和非主键索引差别很小,只不过是主键索引的索引键是一个唯一且非空 的键而已。而且 MyISAM 存
储引擎的索引和 Innodb 的 Secondary Index 的存储结构也基本相同,主要的区别只是 MyISAM 存储引擎在 Leaf Nodes 上面出了存
放索引键信息之外,再存放能直接定位到 MyISAM 数据文件中相应的数据行的信息(如 Row Number ),但并不会存放主键的键值信息。



索引分单列索引和组合索引
单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。
组合索引,即一个索引包含多个列。

MySQL索引类型包括:
普通索引
唯一索引
主键索引
全文索引
空间索引


查看索引

语法 :  
show index from 表名;
show keys from 表名;
desc 表名;

mysql> show index from table_name;
mysql> show keys from table_name;

*************************** 1. row ***************************
        Table: a
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: s_id
    Collation: A
  Cardinality: 7
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 

---------------------------------------------------------------------------------------------------------------------------------------
· Non_unique     如果索引不能包括重复词,则为0。如果可以,则为1。
· Key_name       索引的名称。
· Seq_in_index   索引中的列序列号,从1开始。
· Column_name  列名称。
· Collation          列以什么方式存储在索引中。在MySQL中,有值'A'(升序)或NULL(无分类)。
· Cardinality        索引中唯一值的数目的估计值。通过运行ANALYZE TABLE或myisamchk -a可以更新。基数根据被存储为整数的统计数据来计数,
                        所以即使对于小型表,该值也没有必要是精确的。基数越大,当进行联合时,MySQL使用该索引的机 会就越大。
· Sub_part         如果列只是被部分地编入索引,则为被编入索引的字符的数目。如果整列被编入索引,则为NULL。
· Packed            指示关键字如何被压缩。如果没有被压缩,则为NULL。
· Null                 如果列含有NULL,则含有YES。如果没有,则该列含有NO。
· Index_type      用过的索引方法(BTREE, FULLTEXT, HASH, RTREE)。
· Comment
---------------------------------------------------------------------------------------------------------------------------------------


查看索引使用情况
show status like 'Handler_read%';

如果索引正在工作,Handler_read_key 的值将很高,这个值代表了一个行被索引值读的次数,很低的值表明增加索引得到的性能改善不高,因为索引并不经常使用。
Handler_read_rnd_next 值高意味查询低效,应该建立索引补救。这个值的含义是在数据文件中读下一行的请求数 , 如果你正进行大量的表扫描 , 该值较高 , 通常说明表索引不正确或写入的查询没有利用索引。



我们这里建个表,以供下面测试用
create table t1(id int,usename varchar(16),city varchar(16),age int);



一.普通索引:
是最基本的索引,它没有任何限制

1.创建索引
语法:
create index 索引名 on 表名(列(长度));                           -- 单列索引
create index 索引名 on 表名(列1(长度),列2(长度),...);       -- 组合索引

举例:
CREATE INDEX indexName ON mytable(username(10));               -- 单列索引
CREATE INDEX indexName ON mytable(username(10),city(10));   -- 组合索引

-- indexName为索引名,mytable表名,username和city为列名,10为前缀长度,即索引在该列从最左字符开始存储的信息长度,单位字节
-- 如果是CHAR,VARCHAR类型,前缀长度可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定前缀长度,下同。


2.修改表结构来创建索引
语法:
alter table 表名 add index 索引名(列(长度));                            -- 单列索引
alter table 表名 add index 索引名(列1(长度),列2(长度),...);        -- 单列索引

举列:
ALTER TABLE mytable ADD INDEX indexName (username(10));               -- 单列索引
ALTER TABLE mytable ADD INDEX indexName (username(10),city(10));   -- 组合索引

-- 此处 indexName 索引名可不写,系统自动赋名 username ,username_2 ,username_3,...


3.创建表的时候直接指定
语法:
create table 表名(列1 数据类型,列2 数据类型,...,index 索引名(列(长度));                       -- 单列索引
create table 表名(列1 数据类型,列2 数据类型,...,index 索引名(列1(长度),列2(长度),...);   -- 组合索引

举例:
CREATE TABLE mytable(id INT,username VARCHAR(16),city VARCHAR(16),age INT,INDEX indexName (username(10)));  
CREATE TABLE mytable(id INT,username VARCHAR(16),city VARCHAR(16),age INT,INDEX indexName (username(10),city(10)));
-- INDEX indexName (username(10),city(10))此处indexName 索引名同样可以省略


二.唯一索引:
它与普通索引类似,不同的是:索引列的值必须唯一,但允许有空值。如是组合索引,则列值的组合必须唯一。

有以下几种创建方式(在创建普通索引时关键字 INDEX 前加 UNIQUE):

1.创建索引
语法:
create unique index 索引名 on 表名(列(长度));                                -- 单列索引
create unique index 索引名 on 表名(列1(长度),列2(长度),...);            -- 组合索引

举例:
CREATE UNIQUE INDEX indexName ON mytable(username(10));                    -- 单列索引
CREATE UNIQUE INDEX indexName ON mytable(username(10)),city(10));       -- 组合索引


2.修改表结构来创建索引
语法:
alter table 表名 add unique index 索引名(列(长度));                          -- 单列索引
alter table 表名 add unique index 索引名(列1(长度),列2(长度),...);      -- 组合索引
也或简写成
alter table 表名 add unique 索引名(列(长度));                                -- 单列索引
alter table 表名 add unique 索引名(列1(长度),列2(长度),...);            -- 组合索引

举例:
ALTER TABLE mytable ADD UNIQUE INDEX indexName (username(10));             -- 单列索引
ALTER TABLE mytable ADD UNIQUE INDEX indexName (username(10),city(10)); -- 组合索引
也可简写成
ALTER TABLE mytable ADD UNIQUE indexName (username(10));
ALTER TABLE mytable ADD UNIQUE indexName (username(10),city(10));


3.创建表的时候直接指定
语法:
create table 表名(列1 数据类型,列2 数据类型,...,unique index 索引名(列(长度));                       -- 单列索引
create table 表名(列1 数据类型,列2 数据类型,...,unique index 索引名(列1(长度),列2(长度),...);   -- 组合索引
也或简写成
create table 表名(列1 数据类型,列2 数据类型,...,unique 索引名(列(长度));
create table 表名(列1 数据类型,列2 数据类型,...,unique 索引名(列1(长度),列2(长度),...));

举例:
CREATE TABLE mytable(id INT,username VARCHAR(16),city VARCHAR(16),age INT,UNIQUE INDEX indexName (username(10)));   --也可简写成 UNIQUE indexName (username(10))
CREATE TABLE mytable(id INT,username VARCHAR(16),city VARCHAR(16),age INT,UNIQUE INDEX indexName (username(10),city(10)));



三.主键索引
它是一种特殊的唯一索引,不允许有空值。在建表的时候同时创建的主键即为主键索引
主键索引无需命名,一个表只能有一个主键。主键索引同时可是唯一索引或者全文索引,但唯一索引或全文索引不能共存在同一索引

1.修改表结构来创建索引
语法:
alter table 表名 add primary key (列);
alter table 表名 add primary key (列1,列2,...);

举例:
ALTER TABLE mytable ADD PRIMARY KEY (id);
ALTER TABLE mytable ADD PRIMARY KEY (id,name);

2.创建表的时候直接指定
语法:
create table 表名(列1 数据类型,列2 数据类型,...,primary key(列));               -- 单列索引
create table 表名(列1 数据类型,列2 数据类型,...,primary key(列1,列2,...));    -- 组合索引

举例:
CREATE TABLE mytable(id INT,username VARCHAR(16),city VARCHAR(16),age INT,PRIMARY KEY(id));                 -- 单列索引
CREATE TABLE mytable(id INT,username VARCHAR(16),city VARCHAR(16),age INT,PRIMARY KEY(id,username));   -- 组合索引



四.全文索引
InnoDB存储引擎不支持全文索引

1.创建索引
语法:
create fulltext index 索引名 on 表名(列(长度));                                   -- 单列索引
create fulltext index 索引名 on 表名(列1(长度),列2(长度),...);               -- 组合索引

举例:
CREATE FULLTEXT INDEX indexName ON mytable(username(10));
CREATE FULLTEXT INDEX indexName ON mytable(username(10),city(10));

2.修改表结构来创建索引
语法:
alter table 表名 add fulltest index 索引名(列(长度));                        -- 单列索引
alter table 表名 add fulltest index 索引名(列1(长度),列2(长度),...);    -- 组合索引

举例:
ALTER TABLE mytable ADD FULLTEXT INDEX indexName (username(10));
也可简写成
ALTER TABLE mytable ADD FULLTEXT indexName (username(10));

3.创建表的时候直接指定
语法:
create table 表名(列1 数据类型,列2 数据类型,...,fulltext index 索引名(列(长度))) engine=myisam;                  -- 单列索引
create table 表名(列1 数据类型,列2 数据类型,...,fulltext index 索引名(列1(长度),列2(长度))) engine=myisam;  -- 组合索引

举例:
CREATE TABLE mytable(id INT,username VARCHAR(16),city VARCHAR(16),age INT,FULLTEXT INDEX indexName (username(10))) ENGINE=MYISAM;  //可简写成 FULLTEXT indexName (username(10))
CREATE TABLE mytable(id INT,username VARCHAR(16),city VARCHAR(16),age INT,FULLTEXT INDEX indexName (username(10),city(10))) ENGINE=MYISAM;

建表时创建全文索引,要设置该表的存储引擎为MYISAM,新版mysql默认InnoDB存储引擎不支持全文索引


五.空间索引
必须在MyISAM类型的表中创建,且空间类型的字段必须为非空

语法:
create table 表名(列1 数据类型,列2 数据类型,...,spatial index 索引名(列(长度)));
create table 表名(列1 数据类型,列2 数据类型,...,spatial index 索引名(列1(长度),列2(长度),...));

举例:
创建表t5,在空间类型为GEOMETRY的字段上创建空间索引,SQL语句如下:
CREATE TABLE t5( g GEOMETRY NOT NULL, SPATIAL INDEX spatIdx(g) )ENGINE=MyISAM;


六.删除索引

语法:
drop index 索引名 on 表名;

举列:
DROP INDEX indexName ON mytable;


七.练习

创建索引

CREATE INDEX和ALTER TABLE两种方式
ALTER TABLE table_name ADD INDEX index_name (column_list)    #增加普通索引
ALTER TABLE table_name ADD UNIQUE (column_list)                   #增加唯一索引
ALTER TABLE table_name ADD PRIMARY KEY (column_list)           #增加主键索引

CREATE INDEX 增加普通索引、UNIQUE索引
CREATE INDEX index_name ON table_name (column_list)
CREATE UNIQUE INDEX index_name ON table_name (column_list)

Create INDEX不能创建PRIMARY KEY索引
添加索引时 CREATE INDEX index_name ON table_name(name(length))可限制长度。如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length。

主键:(不重复):应该添加主键索引 PRIMARY KEY。一个表只能有一个主键。一种特殊的唯一索引,不允许有空值
唯一: 应该添加UNIQUE索引,可以是单列不重复和多列不重复。组合唯一索引,多列不重复要保证组合不重复。索引列的值必须唯一,但允许有空值。
普通索引:添加索引可提高检索的速度。
同一表中索引名称不能重复。


删除索引

ALTER TABLE或DROP INDEX删除索引
语法:DROP INDEX index_name ON talbe_name;
         ALTER TABLE table_name DROP INDEX index_name;

对于组合索引,如从表中删除了某列,则索引会受到影响。则该列也会从索引中删除。如果删除组成索引的所有列,则整个索引将被删除。

【例9.1】在book表中的year_publication字段上建立普通索引,SQL语句如下:
CREATE TABLE book
(
bookid              INT NOT NULL,
bookname            VARCHAR(255) NOT NULL,
authors             VARCHAR(255) NOT NULL,
info                VARCHAR(255) NULL,
comment             VARCHAR(255) NULL,
year_publication    YEAR NOT NULL,
INDEX(year_publication)
);

该语句执行完毕之后,使用SHOW CREATE TABLE查看表结构:
 SHOW CREATE table book \G
*************************** 1. row ***************************
       Table: book
CREATE Table: CREATE TABLE `book` (
  `bookid` int(11) NOT NULL,
  `bookname` varchar(255) NOT NULL,
  `authors` varchar(255) NOT NULL,
  `info` varchar(255) DEFAULT NULL,
  `comment` varchar(255) DEFAULT NULL,
  `year_publication` year(4) NOT NULL,
  KEY `year_publication` (`year_publication`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

由结果可以看到,book1表的year_publication字段上成功建立索引,其索引名称year_publication为MySQL自动添加。使用EXPLAIN语句查看索引是否正在使用:
 explain select * from book where year_publication=1990 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: book
         type: ref
possible_keys: year_publication
          key: year_publication
      key_len: 1
          ref: const
         rows: 1
        Extra:
1 row in set (0.05 sec)



【例9.2】创建一个表t1,在表中的id字段上使用UNIQUE关键字创建唯一索引。
CREATE TABLE t1
(
id    INT NOT NULL,
name CHAR(30) NOT NULL,
UNIQUE INDEX UniqIdx(id)
);

该语句执行完毕之后,使用SHOW CREATE TABLE查看表结构:
 SHOW CREATE table t1 \G
*************************** 1. row ***************************
       Table: t1
CREATE Table: CREATE TABLE `t1` (
  `id` int(11) NOT NULL,
  `name` char(30) NOT NULL,
  UNIQUE KEY `UniqIdx` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

由结果可以看到,id字段上已经成功建立了一个名为UniqIdx的唯一索引。


【例9.3】创建一个表t2,在表中的name字段上创建单列索引。
表结构如下:
CREATE TABLE t2
(
id   INT NOT NULL,
name CHAR(50) NULL,
INDEX SingleIdx(name(20))
);

该语句执行完毕之后,使用SHOW CREATE TABLE查看表结构:
 SHOW CREATE table t2 \G
*************************** 1. row ***************************
       Table: t2
CREATE Table: CREATE TABLE `t2` (
  `id` int(11) NOT NULL,
  `name` char(50) DEFAULT NULL,
  KEY `SingleIdx` (`name`(20))
) ENGINE=InnoDB DEFAULT CHARSET=utf8

由结果可以看到,id字段上已经成功建立了一个名为SingleIdx的单列索引,索引长度为20。


【例9.4】创建表t3,在表中的id、name和age字段上建立组合索引,SQL语句如下:
CREATE TABLE t3
(
id    INT NOT NULL,
name CHAR(30)  NOT NULL,
age  INT NOT  NULL,
info VARCHAR(255),
INDEX MultiIdx(id, name, age(100))
);
该语句执行完毕之后,使用SHOW CREATE TABLE查看表结构:
 SHOW CREATE table t3 \G
*************************** 1. row ***************************
       Table: t3
CREATE Table: CREATE TABLE `t3` (
  `id` int(11) NOT NULL,
  `name` char(30) NOT NULL,
  `age` int(11) NOT NULL,
  `info` varchar(255) DEFAULT NULL,
  KEY `MultiIdx` (`id`,`name`,`age`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

由结果可以看到,id、name和age字段上已经成功建立了一个名为MultiIdx的组合索引。

组合索引可起几个索引的作用,但是使用时并不是随便查询哪个字段都可以使用索引,而是遵从“最左前缀”:利用索引中最左边的列集来匹配行,这样的列集称为最左前缀。例如这里由id、name和age 3个字段构成的索引,索引行中按id/name/age的顺序存放,索引可以搜索下面字段组合:(id, name, age)、(id, name)或者id。如果列不构成索引最左面的前缀,MySQL不能使用局部索引,如(age)或者(name,age)组合则不能使用索引查询。

在t3表中,查询id和name字段,使用EXPLAIN语句查看索引的使用情况:
 explain select * from t3 where id=1 AND name='joe' \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t3
         type: ref
possible_keys: MultiIdx
          key: MultiIdx
      key_len: 94
          ref: const,const
         rows: 1
        Extra: Using where
1 row in set (0.00 sec)
可以看到,查询id和name字段时,使用了名称MultiIdx的索引,如果查询(name,age)组合或者单独查询name和age字段,结果如下:
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t3
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 1
        Extra: Using where
此时,possible_keys和key值为NULL,并没有使用在t3表中创建的索引进行查询。



5.创建全文索引
FULLTEXT全文索引可以用于全文搜索。只有MyISAM存储引擎支持FULLTEXT索引,并且只为CHAR、VARCHAR和TEXT列。索引总是对整个列进行,不支持局部(前缀)索引。


【例9.5】创建表t4,在表中的info字段上建立全文索引,SQL语句如下:
CREATE TABLE t4
(
id    INT NOT NULL,
name CHAR(30) NOT NULL,
age  INT NOT NULL,
info VARCHAR(255),
FULLTEXT INDEX FullTxtIdx(info)
) ENGINE=MyISAM;

因为MySQL5.6中默认存储引擎为InnoDB,在这里创建表时需要修改表的存储引擎为MyISAM,不然创建索引会出错。

语句执行完毕之后,使用SHOW CREATE TABLE查看表结构:
 SHOW CREATE table t4 \G
*************************** 1. row ***************************
       Table: t4
CREATE Table: CREATE TABLE `t4` (
  `id` int(11) NOT NULL,
  `name` char(30) NOT NULL,
  `age` int(11) NOT NULL,
  `info` varchar(255) DEFAULT NULL,
  FULLTEXT KEY `FullTxtIdx` (`info`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

由结果可以看到,info字段上已经成功建立了一个名为FullTxtIdx的FULLTEXT索引。全文索引非常适合于大型数据集,对于小的数据集,它的用处可能比较小。



6.创建空间索引
空间索引必须在MyISAM类型的表中创建,且空间类型的字段必须为非空。

【例9.6】创建表t5,在空间类型为GEOMETRY的字段上创建空间索引,SQL语句如下:
CREATE TABLE t5
( g GEOMETRY NOT NULL, SPATIAL INDEX spatIdx(g) )ENGINE=MyISAM;

该语句执行完毕之后,使用SHOW CREATE TABLE查看表结构:
 SHOW CREATE table t5 \G


【例9.7】在book表中的bookname字段上建立名为BkNameIdx的普通索引,SQL语句如下:
ALTER TABLE book ADD INDEX BkNameIdx ( bookname(30) );

添加索引之前,使用SHOW INDEX语句查看指定表中创建的索引:
 SHOW INDEX FROM book \G

下面使用ALTER TABLE 在bookname字段上添加索引,SQL语句如下:
ALTER TABLE book ADD INDEX BkNameIdx( bookname(30) );

使用SHOW INDEX语句查看表中的索引:
 SHOW INDEX FROM book \G

【例9.8】在book表的bookId字段上建立名称为UniqidIdx 的唯一索引,SQL语句如下:
ALTER TABLE book ADD UNIQUE INDEX UniqidIdx ( bookId );

使用SHOW INDEX语句查看表中的索引:
 SHOW INDEX FROM book \G

【例9.9】在book表的comment字段上建立单列索引,SQL语句如下:
ALTER TABLE book ADD INDEX BkcmtIdx ( comment(50) );
使用SHOW INDEX语句查看表中的索引:

【例9.10】在book表的authors和info字段上建立组合索引,SQL语句如下:
ALTER TABLE book ADD INDEX BkAuAndInfoIdx ( authors(20),info(50) );
使用SHOW INDEX语句查看表中的索引:

【例9.11】创建表t6,在t6表上使用ALTER TABLE创建全文索引,SQL语句如下:
首先创建表t6,语句如下:
CREATE TABLE t6
(
id    INT NOT NULL,
info  CHAR(255)
) ENGINE=MyISAM;

注意修改ENGINE参数为MyISAM,MySQL默认引擎InnoDB不支持全文索引。

使用ALTER TABLE语句在info字段上创建全文索引:
ALTER TABLE t6 ADD FULLTEXT INDEX infoFTIdx ( info );

使用SHOW INDEX语句查看索引:
 SHOW index from t6 \G

【例9.12】创建表t7,在t7的空间数据类型字段g上创建名称为spatIdx的空间索引,SQL语句如下:
CREATE TABLE t7 ( g GEOMETRY NOT NULL )ENGINE=MyISAM;

使用ALTER TABLE在表t7的g字段建立空间索引:
ALTER TABLE t7 ADD SPATIAL INDEX spatIdx(g);

使用SHOW INDEX语句查看索引:
 SHOW index from t7 \G

2.使用CREATE INDEX创建索引
CREATE INDEX语句可以在已经存在的表上添加索引,MySQL中CREATE INDEX被映射到一个ALTER TABLE语句上,基本语法结构为:
CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
ON table_name (col_name[length],…) [ASC | DESC]

可以看到CREATE INDEX语句和ALTER INDEX语句的语法基本一样,只是关键字不同。

在这里,使用相同的表book,假设该表中没有任何索引值,创建book表语句如下:
CREATE TABLE book
(
bookid              INT NOT NULL,
bookname            VARCHAR(255) NOT NULL,
authors             VARCHAR(255) NOT NULL,
info                VARCHAR(255) NULL,
comment             VARCHAR(255) NULL,
year_publication    YEAR NOT NULL
);

提示:读者可以将该数据库中的book表删除,按上面的语句重新建立,然后进行下面的操作。


【例9.13】在book表中的bookname字段上建立名为BkNameIdx的普通索引,SQL语句如下:
CREATE INDEX BkNameIdx ON book(bookname);
语句执行完毕之后,将在book表中创建名称为BkNameIdx的普通索引。读者可以使用SHOW INDEX或者SHOW CREATE TABLE语句查看book表中的索引,其索引内容与前面介绍相同。


【例9.14】在book表的bookId字段上建立名称为UniqidIdx 的唯一索引,SQL语句如下:
CREATE UNIQUE INDEX UniqidIdx  ON book ( bookId );
语句执行完毕之后,将在book表中创建名称为UniqidIdx 的唯一索引。


【例9.15】在book表的comment字段上建立单列索引,SQL语句如下:
CREATE INDEX BkcmtIdx ON book(comment(50) );
语句执行完毕之后,将在book表的comment字段上建立一个名为BkcmtIdx的单列索引,长度为50。


【例9.16】在book表的authors和info字段上建立组合索引,SQL语句如下:
CREATE INDEX BkAuAndInfoIdx ON book ( authors(20),info(50) );
语句执行完毕之后,将在book表的authors和info字段上建立了一个名为BkAuAndInfoIdx的组合索引,authors的索引序号为1,长度为20,info的索引序号为2,长度为50。


【例9.17】删除表t6,重新建立表t6,在t6表中使用CREATE INDEX语句,在CHAR类型的info字段上创建全文索引,SQL语句如下:
首先删除表t6,并重新建立该表,分别输入下面语句:
 drop table t6;
Query OK, 0 rows affected (0.00 sec)

 CREATE TABLE t6
     (
     id    INT NOT NULL,
     info  CHAR(255)
     ) ENGINE=MyISAM;
Query OK, 0 rows affected (0.00 sec)
使用CREATE INDEX在t6表的info字段上创建名称为infoFTIdx的全文索引:
CREATE FULLTEXT INDEX ON t6(info);

语句执行完毕之后,将在t6表中创建名称为infoFTIdx的索引,该索引在info字段上创建,类型为FULLTEXT,允许空值。


【例9.18】删除表t7,重新创建表t7,在t7表中使用CREATE INDEX语句,在空间数据类型字段g上创建名称为spatIdx的空间索引,SQL语句如下:
首先删除表t7,并重新建立该表,分别输入下面语句:
 drop table t7;
Query OK, 0 rows affected (0.00 sec)

 CREATE TABLE t7 ( g GEOMETRY NOT NULL )ENGINE=MyISAM;
Query OK, 0 rows affected (0.00 sec)
使用CREATE INDEX语句在表t7的g字段建立空间索引,
CREATE SPATIAL INDEX spatIdx ON t7 (g);
语句执行完毕之后,将在t7表中创建名称为spatIdx的空间索引,该索引在g字段上创建。


9.3  删除索引
MySQL中删除索引使用ALTER TABLE或者DROP INDEX语句,两者可实现相同的功能,DROP INDEX语句在内部被映射到一个ALTER TABLE语句中。
1.使用ALTER TABLE删除索引
ALTER TABLE删除索引的基本语法格式如下:
ALTER TABLE table_name DROP INDEX index_name;


【例9.19】删除book表中的名称为UniqidIdx的唯一索引,SQL语
句如下:
首先查看book表中是否有名称为UniqidIdx的索引,输入SHOW语句如下:
 SHOW CREATE table book \G
*************************** 1. row ***************************
       Table: book
CREATE Table: CREATE TABLE `book` (
  `bookid` int(11) NOT NULL,
  `bookname` varchar(255) NOT NULL,
  `authors` varchar(255) NOT NULL,
  `info` varchar(255) DEFAULT NULL,
  `year_publication` year(4) NOT NULL,
  UNIQUE KEY `UniqidIdx` (`bookid`),
  KEY `BkNameIdx` (`bookname`),
  KEY `BkAuAndInfoIdx` (`authors`(20),`info`(50))
) ENGINE=InnoDB DEFAULT CHARSET=utf8

查询结果可以看到,book表中有名称为UniqidIdx的唯一索引,该索引在bookid字段上创建,下面删除该索引,输入删除语句如下:
 ALTER TABLE book DROP INDEX UniqidIdx;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

语句执行完毕,使用SHOW语句查看索引是否被删除:
 SHOW CREATE table book \G
*************************** 1. row ***************************
       Table: book
CREATE Table: CREATE TABLE `book` (
  `bookid` int(11) NOT NULL,
  `bookname` varchar(255) NOT NULL,
  `authors` varchar(255) NOT NULL,
  `info` varchar(255) DEFAULT NULL,
  `year_publication` year(4) NOT NULL,
  KEY `BkNameIdx` (`bookname`),
  KEY `BkAuAndInfoIdx` (`authors`(20),`info`(50))
) ENGINE=InnoDB DEFAULT CHARSET=utf8

由结果可以看到,book表中已经没有名称为uniqidIdx的唯一索引,删除索引成功。
添加AUTO_INCREMENT约束字段的唯一索引不能被删除。


2.使用DROP INDEX语句删除索引
DROP INDEX删除索引的基本语法格式如下:
DROP INDEX index_name ON table_name;


【例9.20】删除book表中名称为BkAuAndInfoIdx的组合索引,SQL语句如下:
 DROP INDEX BkAuAndInfoIdx ON book;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

语句执行完毕,使用SHOW语句查看索引是否被删除:
 SHOW CREATE table book \G
*************************** 1. row ***************************
       Table: book
CREATE Table: CREATE TABLE `book` (
  `bookid` int(11) NOT NULL,
  `bookname` varchar(255) NOT NULL,
  `authors` varchar(255) NOT NULL,
  `info` varchar(255) DEFAULT NULL,
  `year_publication` year(4) NOT NULL,
  KEY `BkNameIdx` (`bookname`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

可以看到,book表中已经没有名称为BkAuAndInfoIdx的组合索引,删除索引成功。
删除表中的列时,如果要删除的列为索引的组成部分,则该列也会从索引中删除。如果组成索引的所有列都被删除,则整个索引将被删除。

猜你喜欢

转载自blog.csdn.net/wangminglong1989/article/details/81556746