在大多数据库系统中,数据库读取(查询)数据的次数远大于写入数据的次数,因此,如何优化数据读取的效率是数据库系统的主要工作之一。
数据库索引是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中的数据。
索引是一种以空间代价换取时间效率提升的方法。
- 聚集索引(Clustered Index)/聚簇索引
- 非聚集索引(Non-Clustered Index)/辅助索引/二级索引
(一)聚集索引
聚集索引也称聚簇索引:将数据存储与索引放到一起,索引结构的叶子节点保存所有数据。在聚集索引中,表中行的逻辑顺序与主键值的索引顺序相同,因此,一个表只有一个聚集索引
1. 创建索引
创建方式一:在建表时定义主键

创建方式二:修改表时创建,如表是从外部导入的则没有主键。
ALTER TABLE stu ADD PRIMARY KEY(sno);
问题:如果不定义主键能否创建聚集索引?
如果不定义主键,系统将使用第一个唯一(UNIQUE)索引创建聚集索引。 如果表没有主键,且没有唯一索引,则系统会自动生成一个rowid作为隐藏的聚集索引主键。
(二)非聚集索引
非聚集索引也称二级索引或辅助索引,除聚集索引外其他索引都称为二级索引。
二级索引是在非主键字段上创建的索引;
- 创建索引
(1)CREATE TABLE tudent(
...... INDEX idx_sname(sname)
)CHARSET=gbk;
(2)CREATE INDEX idx_sname ON student(sname);
a.联合索引也称多列索引,是建立在多个字段上的索引;
CREATE INDEX idx_sname_birthday ON student(sname,birthday);
b.全文索引:能够将存储于数据库中的文本中的任意内容查找出来的技术。
CREATE FULLTEXT INDEX ft_remarks ON student(remarks);
c. 前缀索引
CREATE INDEX pf_cname ON course ( cname(4) );
算法:
SELECT COUNT(DISTINCT LEFT(cname,3))/COUNT(cname) FROM course
length值取3时,执行结果为0.7778,
SELECT COUNT(DISTINCT LEFT(cname,4))/COUNT(cname) FROM course
length值取4时,执行结果为1.0000。
总结:
1.建表时创建索引
CREATE TABLE 表名(字段列表,[UNIQUE | FULLTEXT | SPATIAL] INDEX | KEY <index_name> (<column_name>[(length)] [ASC | DESC] ,...... ));
例:
(1)在sname字段和dept字段上创建联合索引idx_sname_dept;
(2)在remarks字段上创建全文索引ft_remarks。
CREATE TABLE student(
...... INDEX idx_sname_dept(sname,dept),
FULLTEXT ft_remarks(remarks)) ;
2.建表后创建索引
CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX <index_name> ON <table_name> (<column_name>[(length)] [ASC | DESC] ...... ) ;
【例】在course表的cname字段上创建唯一索引uk_cname
CREATE UNIQUE INDEX uk_cname ON course (cname);
【例】在course表的cname字段上创建前缀索引pf_cname
CREATE INDEX pf_cname ON course ( cname(4) );
3.修改表结构添加索引
ALTER TABLE <table_name> ADD [UNIQUE | FULLTEXT | SPATIAL] INDEX <index_name> (<column_name>[(length)] [ASC | DESC]......) ;
【例】在score表的sno字段和cno字段创建组合唯一索引,约束同一个学生的同一门课成绩只能出现一次。
ALTER TABLE score ADD UNIQUE INDEX idx_sno_cno( sno, cno );
查看索引:
SHOW INDEX FROM <table_name> [ where <condition>];
【例】查看course表中的索引。
SHOW INDEX FROM course;
【例】查看student表中的索引使用。
EXPLAIN SELECT * FROM student WHERE sname LIKE '王%';
删除索引
可以通过ALTER TABLE语句和DROP INDEX语句两种方式删除索引。
ALTER TABLE <table_name> DROP INDEX <index_name>;
DROP INDEX <index_name> ON <table_name> ;
【例】删除student表中的idx_sname_dept索引。
ALTER TABLE student1 DROP INDEX idx_sname_dept;
【例】删除score表中的uk_sno_cno索引。
DROP INDEX uk_sno_cno ON score;
(三)索引类别
(1)PRIMARY:主键索引,索引列值唯一且不能为空;
(2)INDEX:普通索引,索引列没有任何限制。
(3)UNIQUE:唯一索引,索引列的值必须是唯一的,但允许有空值。
(4)FULLTEXT:全文索引。
(5)SPATIAL:空间索引,对空间数据类型的字段建立的索引(自学)。
(6)哈希索引(也称HASH索引):对于每一条行数据,存储引擎对所有的索引列计算一个哈希码。将所有的哈希码存储在索引中,同时在哈希表中保存指向每一个数据行的指针。系统自建。
(四)索引的设计原则
(1)索引命名符合规范;
主键索引名为 pk_字段名;唯一索引名为 uk_字段名;普通索引名为 idx_字段名。
(2)条件子句中频繁使用的字段、数字型的字段、存储空间较小的字段适合建立索引;
选择在WHERE子句、GROUP BY子句、ORDER BY子句或表与表之间连接运算等频繁使用的字段上建立索引
(3)重复值较高的字段、更新频繁的字段不适合建立索引;
(4)索引字段的值很长,最好使用字段值的前缀建立索引;
CREATE INDEX idx_came ON course(cname(6));
(5)限制索引的数量,否则会降低系统效率;
(五)索引总结
优点:使用索引,可以在查询的过程中,提高系统的性能。
缺点:占用更多的存储空间;索引的维护成本很高,每次新增、删除数据都需要整理B+树结构(结点分裂、合并)拖慢了增删改的速度。
索引必须根据表中的列数据的使用特性进行创建,而不能随意建立,在什么情况下使用索引、使用什么类型的索引以及在什么情况下不使用索引,需要根据数据库的设计需求或使用经验来判断。