一、什么是索引
索引就像是书籍的目录一样,如果在字段上建立了索引,那么以索引列为查询条件时可以加快查询速度。常用的索引有:
- 主键索引
- 普通索引
- 联合索引
- 唯一索引
二、索引的使用
(一)主键索引
查询数据库时,按照主键索引是最快的,主键是唯一的。在创建主键索引时,有两种情况:
1、建表时创建
在创建表时可以创建主键索引。
mysql> create table userinfo( -> id int(4) not null auto_increment, -> username varchar(32) default null, -> age tinyint(2) not null default 0, -> primary key(id) -> ); Query OK, 0 rows affected (0.01 sec)
通过primary key和auto_increment来创建主键。创建后可以通过desc命令查看:
mysql> desc userinfo; +----------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------+-------------+------+-----+---------+----------------+ | id | int(4) | NO | PRI | NULL | auto_increment | | username | varchar(32) | YES | | NULL | | | age | tinyint(2) | NO | | 0 | | +----------+-------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec)
2、建表后增加
假如现在的表没有主键,建表语句如下:

create table userinfo( id int(4) not null, username varchar(32) default null, age tinyint(2) not null default 0 );
现在增加主键:
mysql> alter table userinfo change id id int primary key auto_increment; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0
(二)普通索引
普通索引可以创建多个,它唯一的作用就是加快查询速度,它的创建修改如下:
1、建表时创建
mysql> create table userinfo( -> id int(4) not null auto_increment, -> username varchar(32) default null, -> age tinyint(2) not null default 0, -> primary key(id), -> KEY index_name(username) -> ); Query OK, 0 rows affected (0.00 sec) mysql> desc userinfo; +----------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------+-------------+------+-----+---------+----------------+ | id | int(4) | NO | PRI | NULL | auto_increment | | username | varchar(32) | YES | MUL | NULL | | | age | tinyint(2) | NO | | 0 | | +----------+-------------+------+-----+---------+----------------+ 3 rows in set (0.01 sec)
在建表时使用KEY index_name(column)来创建普通索引,注意的是在唯一值多的列上创建索引查询效率更高。
2、建表后增加
-- 删除索引 mysql> alter table userinfo drop index index_name; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 -- 查看 mysql> desc userinfo; +----------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------+-------------+------+-----+---------+----------------+ | id | int(4) | NO | PRI | NULL | auto_increment | | username | varchar(32) | YES | | NULL | | | age | tinyint(2) | NO | | 0 | | +----------+-------------+------+-----+---------+----------------+ 3 rows in set (0.04 sec) -- 添加索引 mysql> alter table userinfo add index index_username(username); Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0
3、对字段的前n个字符创建普通索引
当表中的列的内容比较多时,并且列的内容的前n个字符已经接近唯一时,可以对列的前n个字符建立索引,而无需对整个列建立索引,这样可以节省创建索引占用的系统空间,以及降低读取和更新维护索引消耗的资源。
-- 创建索引的语法 create index index_name on userinfo(username(5)) -- 创建实例 mysql> create index index_username on userinfo(username(5)); Query OK, 0 rows affected (0.03 sec) Records: 0 Duplicates: 0 Warnings: 0 -- 查看索引 mysql> show index from userinfoG; *************************** 1. row *************************** Table: userinfo Non_unique: 0 Key_name: PRIMARY Seq_in_index: 1 Column_name: id Collation: A Cardinality: 0 Sub_part: NULL Packed: NULL Null: Index_type: BTREE Comment: Index_comment: *************************** 2. row *************************** Table: userinfo Non_unique: 1 Key_name: index_username Seq_in_index: 1 Column_name: username Collation: A Cardinality: 0 Sub_part: 5 Packed: NULL Null: YES Index_type: BTREE Comment: Index_comment: 2 rows in set (0.00 sec)
(三)联合索引
如何表中有多个列,可以基于这多个列创建联合索引:
- 基于多列创建联合索引
- 基于多列的前n个字符创建联合索引
1、基于多列创建联合索引
-- 删除之前的普通索引 mysql> drop index index_username on userinfo; Query OK, 0 rows affected (0.04 sec) Records: 0 Duplicates: 0 Warnings: 0 -- 创建联合索引 mysql> create index index_username_age on userinfo(username,age); Query OK, 0 rows affected (0.05 sec) Records: 0 Duplicates: 0 Warnings: 0 -- 查看索引 mysql> show index from userinfoG; *************************** 1. row *************************** Table: userinfo Non_unique: 0 Key_name: PRIMARY Seq_in_index: 1 Column_name: id Collation: A Cardinality: 0 Sub_part: NULL Packed: NULL Null: Index_type: BTREE Comment: Index_comment: *************************** 2. row *************************** Table: userinfo Non_unique: 1 Key_name: index_username_age Seq_in_index: 1 Column_name: username Collation: A Cardinality: 0 Sub_part: NULL Packed: NULL Null: YES Index_type: BTREE Comment: Index_comment: *************************** 3. row *************************** Table: userinfo Non_unique: 1 Key_name: index_username_age Seq_in_index: 2 Column_name: age Collation: A Cardinality: 0 Sub_part: NULL Packed: NULL Null: Index_type: BTREE Comment: Index_comment: 3 rows in set (0.01 sec)
2、基于多列的前n个字符创建联合索引
-- 删除联合索引 mysql> drop index index_username_age on userinfo; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 -- 创建联合索引 mysql> create index index_username_age on userinfo(username(5),age(1)); Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0
3、创建表时创建
create table userinfo( id int(4) not null auto_increment, username varchar(32) default null, age tinyint(2) not null default 0, primary key(id), KEY index_name(username,age) );
注意的是按条件列查询数据时,联合索引是有前缀生效特性的,列入index(col1,col2,col3)是col1或者col1,col2或者col1,col2,col3生效,其余的比如col2,col3等不生效。
(四)唯一索引
如果想创建某列或者几列的值是唯一的,那么可以创建唯一非主键索引。
-- 创建唯一非主键索引 mysql> create unique index index_uni_username on userinfo(username); Query OK, 0 rows affected (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0 -- 查看表结构 mysql> desc userinfo; +----------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------+-------------+------+-----+---------+----------------+ | id | int(4) | NO | PRI | NULL | auto_increment | | username | varchar(32) | YES | UNI | NULL | | | age | tinyint(2) | NO | | 0 | | +----------+-------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec)
三、总结
(一)索引的创建与生效条件
索引虽然可以加快查询速度,但是并非可以将所有的列都加上索引。因为索引不但占用系统空间,而且在更新数据库时还需要维护索引数据。所以对于小表(几百行)以及读取少,写的多的业务没有必要建立索引。
对于select username,age where id = ...这样的语句,索引列应该建立在where语句后的列上,而非建立在select这样的查询列上。另外就是尽量将索引建立在唯一值多的列上面。
(二)创建索引的命令
-- create或者alter均可 -- 创建主键索引 alter table userinfo change id id int primary key auto_increment -- 删除主键索引 alter table userinfo drop primary key -- 创建普通索引 alter table userinfo add index index_username(username) -- 根据列前n个字符创建普通索引 create index index_username on userinfo(username(5)) -- 删除普通索引 alter table userinfo drop index index_username drop index index_username on userinfo -- 根据多个列创建联合索引 create index index_username_age on userinfo(username,age) -- 根据多个列前n个字符创建联合索引 create index index_username_age on userinfo(username(5),age(1)) -- 创建唯一索引 create unique index index_uni_username on userinfo(username)