1. 索引的相关概念
1.1 索引概述
索引的本质:索引是数据结构,可以简单理解为“排好序的快速查找数据结构”,满足特定查找算法。这些数据结构以某种方式指向数据,这样就可以在这些数据结构的基础上实现"高级查找算法" 。
个人理解:索引就是在存储引擎中,将数据库数据以某种数据结构(B+树)进行保存,而此数据结构是利于查询操作的,可以加快数据库数据查询的速度。创建索引的过程就是在存储层面构建数据结构的过程。索引创建后,相关列的查询操作可以直接利用这个数据结构完成。
1.2 优缺点
1.2.1 优点
(1)提高数据查询的效率,降低数据库的IO成本,这也是创建索引最主要的原因。
(2)在实现数据的参考完整性方面,可以加速表和表之间的连接。换句话说,对于有依赖关系的子表和父表联合查询时,可以提高查询速度。
(3)在使用分组和排序子句进行数据查询时,可以显著 减少查询中分组和排序的时间,降低了CPU的消耗。
1.2.2 缺点
(1)创建索引和维护索引要耗费时间,并且随着数据量的增加,所耗费的时间也会增加。
(2)索引需要占磁盘空间,除了数据表占数据空间之 外,每一个索引还要占一定的物理空间, 存储在磁盘上 ,如果有大量的索引,索引文件就可能比数据文件更快达到最大文件尺寸。
(3)虽然索引大大提高了查询速度,同时却会降低更新表的速度。当对表中的数据进行增加、删除和修改的时候,索引也要动态地维护,这样就降低了数据的维护速度。
1.3 索引的使用原则
1.3.1 适合创建索引的情况
(1)字段的数值有唯一性的限制
(2)频繁作为 WHERE 查询条件的字段
(3)经常 GROUP BY 和 ORDER BY 的字段
(4)UPDATE、DELETE 的 WHERE 条件字段
(5)DISTINCT 字段需要创建索引
(6)多表 JOIN 连接操作时,对 WHERE 条件字段和用于连接的字段创建索引
(7)使用列的类型小的创建索引
(8)使用字符串前缀创建索引,参考count(distinct left(列名, 索引长度))/count(*)来确定索引长度,越接近于1越好,说明越有区分度
(9)区分度高(散列性高)的列适合作为索引,参考公式select count(distinct a) / count(*) from t1 计算区分度,越接近1越好
(10)使用最频繁的列放到联合索引的左侧
(11)在多个字段都要创建索引的情况下,联合索引优于单值索引
1.3.2 不适合创建索引的情况
(1)在where中使用不到的字段,不要设置索引
(2)数据量小的表最好不要使用索引
(3)有大量重复数据的列上不要建立索引
(4)避免对经常更新的表创建过多的索引
(5)不建议用无序的值作为索引
(6)删除不再使用或者很少使用的索引
(7)不要定义夯余或重复的索引
2. 创建索引
2.1 创建表的时候创建索引
-- 语法格式
CREATE TABLE table_name [col_name data_type]
[UNIQUE | FULLTEXT | SPATIAL] [INDEX | KEY] [index_name] (col_name [length]) [ASC | DESC]
注意:
* UNIQUE 、 FULLTEXT 和 SPATIAL 为可选参数,分别表示唯一索引、全文索引和空间索引;
* INDEX 与 KEY 为同义词,两者的作用相同,用来指定创建索引;
* index_name 指定索引的名称,为可选参数,如果不指定,那么MySQL默认col_name为索引名;
* col_name 为需要创建索引的字段列,该列必须从数据表中定义的多个列中选择;
* length 为可选参数,表示索引的长度,只有字符串类型的字段才能指定索引长度;
* ASC 或 DESC 指定升序或者降序的索引值存储。
举例:
--为字段dept_id 创建普通索引
CREATE TABLE emp(
emp_id INT,
emp_name VARCHAR(20),
dept_id INT,
INDEX(dept_id)
);
--为字段emp_name 创建唯一索引
CREATE TABLE emp(
emp_id INT ,
emp_name VARCHAR(20) ,
dept_id INT,
UNIQUE INDEX idx_emp_name(emp_name)
);
--为字段emp_id 创建主键索引
CREATE TABLE emp(
emp_id INT ,
emp_name VARCHAR(20) ,
dept_id INT,
PRIMARY KEY(emp_id)
);
--为字段emp_id, emp_name 创建组合索引
CREATE TABLE emp(
emp_id INT ,
emp_name VARCHAR(20) ,
dept_id INT,
INDEX multi_idx(emp_id, emp_name)
);
2.2 在已经存在的表上创建索引
2.2.1 使用ALTER TABLE语句创建索引
-- 语法格式
ALTER TABLE table_name ADD [UNIQUE | FULLTEXT | SPATIAL] [INDEX | KEY]
[index_name] (col_name[length],...) [ASC | DESC]
举例:
--为字段dept_id 创建普通索引
ALTER TABLE emp ADD INDEX(dept_id)
--为字段emp_name 创建唯一索引
ALTER TABLE emp ADD UNIQUE INDEX idx_emp_name(emp_name)
--为字段emp_id 创建主键索引
ALTER TABLE emp ADD PRIMARY KEY(emp_id)
--为字段emp_id, emp_name 创建组合索引
ALTER TABLE emp ADD INDEX multi_idx(emp_id, emp_name)
2.2.2 使用CREATE INDEX创建索引
-- 语法格式
CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX index_name
ON table_name (col_name[length],...) [ASC | DESC]
举例:
--为字段dept_id 创建普通索引
CREATE INDEX ON emp(dept_id)
--为字段emp_name 创建唯一索引
CREATE UNIQUE INDEX idx_emp_name ON emp(emp_name)
--为字段emp_id, emp_name 创建组合索引
CREATE INDEX multi_idx ON emp(emp_id, emp_name)
3. 删除索引
3.1 使用ALTER TABLE删除索引
-- 语法格式
ALTER TABLE table_name DROP INDEX index_name;
举例:
--为字段dept_id 删除普通索引
ALTER TABLE emp DROP INDEX dept_id
--为字段emp_name 删除唯一索引
ALTER TABLE emp DROP INDEX idx_emp_name
--为字段emp_id, emp_name 删除组合索引
ALTER TABLE emp DROP INDEX multi_idx
3.2 使用DROP INDEX语句删除索引
-- 语法格式
DROP INDEX index_name ON table_name;
举例:
--为字段dept_id 删除普通索引
DROP INDEX dept_id ON emp
--为字段emp_name 删除唯一索引
DROP INDEX idx_emp_name ON emp
--为字段emp_id, emp_name 删除组合索引
DROP INDEX multi_idx ON emp