MySQL(十一)索引的分类和创建原则
索引的创建与设计原则
1 索引的声明与使用
1.1 索引的分类
	MySQL索引包括普通索引、唯一性索引、全文索引、单列索引、多列索引和空间索引
- 按照逻辑结构划分,主要有四种:
普通索引、唯一性索引、主键索引和全文索引 - 按照物理实现方式划分,主要有两种:
聚簇索引和非聚簇索引 - 按照作用字段:
单列索引和多列索引(联合索引) 
多列索引即联合索引,当多个字段构成联合主键的时候则为聚簇索引,否则为非聚簇索引
普通索引
- 在创建普通索引的时候,不需要任何的限制条件,只是用于提高查询速度
 - 这类索引可以创建在
任何数据类型中,其值是否非空和唯一,取决于字段本身的完整性约束 - 创建索引之后,可以直接通过索引进行查询。
 
唯一性索引
- 使用
UNIQUE参数可以设置索引为唯一索引 - 在创建唯一索引的时候,会限制索引的值必须是唯一的,但是允许有空值
 - 在一张表中可以有多个唯一索引。
 
UNIQUE会自动创建唯一索引,并且可以通过删除字段的唯一索引来删除唯一性
主键索引
- 主键索引是一种特殊的唯一索引,也就是
NOT NULL + UNIQUE,也即是聚簇索引 - 一张表中只能有一个主键索引
 
这是由主键索引的物理实现方式(聚簇索引)决定的:数据存储在文件中只能按照一种顺序(主键大小)进行存储
单列索引
- 即在单个字段上创建的索引
 - 单列索引可以是普通索引,也可以是唯一性索引还可以是全文索引,只需要保证对应一个字段即可
 - 一张表可以有多个单列索引
 
多列索引
- 即在多个字段组合上创建一个索引,该索引指向创建时对应的多个字段,可以通过这几个字段进行查询
 - 但是在查询的时候,只有使用了第一个字段时索引才会被使用(和上面一样,这是由主键索引的物理实现方式决定的:数据存储在文件中只能按照一种顺序(一个列的大小)进行存储),即最
左前缀原则 
全文索引

空间索引

1.2 创建索引
 首先创建数据库和表
CREATE DATABASE dbtest2 CHARACTER SET 'utf8'
CREATE TABLE dept (
	dept_id INT PRIMARY KEY AUTO_INCREMENT,
	dept_name VARCHAR(20)
);
CREATE TABLE emp (
	emp_id INT PRIMARY KEY AUTO_INCREMENT,
	emp_name VARCHAR(20) UNIQUE,
	dept_id INT,
	CONSTRAINT emp_dept_id_fk FOREIGN KEY(dept_id) REFERENCES dept(dept_id)
)
① 创建表的时候添加索引
隐式创建索引:在create table的时候,会对
主键约束、唯一性约束和外键约束的字段上,自动地添加相关的索引
显示创建普通索引:语法如下
CREATE TABLE tableName [colName dataType ...]
[UNIQUE | FULLTEXT | SPATIAL] [INDEX | KEY] [indexName] (colName [length]) [ASC | DESC]
- UNIQUE | FULLTEXT | SPATIAL:可选参数,即唯一索引、全文索引和空间索引
 - index和key作用相同,用来指定创建索引,一般情况下使用key
 - indexName:索引名,不指定的话默认为列名
 - colName:列名
 - length:可选参数,表示索引的长度,只有列为字符类型字段才需要指定
 - ASC、DESC:指定索引的排序顺序
 
CREATE TABLE book (
book_id INT,
book_name VARCHAR(100),
AUTHORS VARCHAR(100),
info varchar(100),
COMMENT VARCHAR(100),
year_publication YEAR,
INDEX idx_bname(book_name)
)

通过命令查看索引:
方式一:show create table tableName
mysql> show create table book\G
*************************** 1. row ***************************
Table: book
Create Table: CREATE TABLE `book` (
`book_id` int DEFAULT NULL,
`book_name` varchar(100) DEFAULT NULL,
`AUTHORS` varchar(100) DEFAULT NULL,
`info` varchar(100) DEFAULT NULL,
`COMMENT` varchar(100) DEFAULT NULL,
`year_publication` year DEFAULT NULL,
KEY `idx_bname` (`book_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3
1 row in set (0.01 sec)方式二:show index from tableName;
mysql> show index from book\G
*************************** 1. row ***************************
Table: book
Non_unique: 1 // 表示不是唯一
Key_name: idx_bname
Seq_in_index: 1
Column_name: book_name
Collation: A
Cardinality: 0
Sub_part: NULL
Packed: NULL
Null: YES
Index_type: BTREE
Comment:
Index_comment:
Visible: YES
Expression: NULL
1 row in set (0.09 sec)EXPLAIN性能分析工具
EXPLAIN SELECT * FROM book WHERE book_name = 'mysql'

可以看到查询语句possible_keys可能使用到的索引包括了idx_bname
创建表的时候添加唯一索引
CREATE TABLE book1 (
book_id INT,
book_name VARCHAR(100),
AUTHORS VARCHAR(100),
info varchar(100),
COMMENT VARCHAR(100),
year_publication YEAR,
UNIQUE INDEX uk_idx_cmt(COMMENT)
); INSERT INTO book1 VALUES (1, 'mysql', NULL, NULL, 'mysql高级', NULL)
INSERT INTO book1 VALUES (2, 'mysql', NULL, NULL, 'mysql高级', NULL)
-- [Err] 1062 - Duplicate entry 'mysql高级' for key 'book1.uk_idx_cmt'
INSERT INTO book1 VALUES (2, 'mysql', NULL, NULL, NULL, NULL)
INSERT INTO book1 VALUES (2, 'mysql', NULL, NULL, NULL, NULL)
声明有唯一索引的字段,在添加数据的时候要保证数据的唯一性,但是可以多次添加NULL值,等效于添加唯一性约束
主键索引:通过主键约束的方式定义,即隐式的方式
INSERT INTO book1 VALUES (2, 'mysql', NULL, NULL, NULL, NULL) mysql> show index from book2\G
*************************** 1. row ***************************
Table: book2
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: book_id
Collation: A
Cardinality: 0
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
Visible: YES
Expression: NULL
1 row in set (0.04 sec)
同样删除索引也只能通过删除主键约束的方式:
ALTER TABLE book2
DROP PRIMARY KEY添加自增的主键不能删除
创建单列索引
前面的都是,这里就不再写了
创建联合索引
CREATE TABLE book3 (
book_id INT,
book_name VARCHAR(100),
AUTHORS VARCHAR(100),
info varchar(100),
COMMENT VARCHAR(100),
year_publication YEAR,
INDEX multi_bid_bname_binf(book_id, book_name, info)
)
SHOW INDEX FROM book3;

 Seq_in_index表示索引的排序顺序,该联合索引会按照id、name、info的顺序进行排序,并且查询的时候要求根据
最左前缀原则先查询id才能使用索引EXPLAIN SELECT * FROM book3 WHERE book_id = 1 AND book_name = 'mysql'
-- possible keys : multi_bid_bname_binf EXPLAIN SELECT * FROM book3 WHERE book_name = 'mysql' = 1 AND book_id
-- possible keys : multi_bid_bname_binf EXPLAIN SELECT * FROM book3 WHERE book_name = 'mysql'
-- possible keys : NULL
最左前缀原则是由数据库表真实的物理存储结构决定的,底层使用的B+树按照联合主键的字段顺序大小进行排序,因此使用别的字段值无法进行检索
全文索引

全文检索使用match + against的方式查询:
select * from test4 where Match(name, info) against('检索字符串')
使用全文检索性能相较于like快很多,但是精度差(可能会少数据)
空间索引

② 创建表的时候添加索引
alter table
ALTER TABLE tableName ADD [UNIQUE | FULLTEXT | SPATIAL] INDEX indexName(colName ...)
create index on
CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX indexName ON tableName(colName ...)
1.3 删除索引
	使用场景:当表中存在较多索引并且进行大量增删改操作的时候,可以先进行删除索引的操作,以减少增删改过程对于索引的维护。
- ALTER TABLE DROP INDEX对应ALTER TABLE ADD INDEX
 
ALTER TABLE book3
DROP INDEX multi_bid_bname_binf
- DROP INDEX ON 对应 CREATE INDEX ON
 
DROP INDEX multi_bid_bname_binf ON book3
对于使用
AUTO_INCREMENT约束的字段不能删除其主键或者索引,前面页提到过,因为AUTO_INCREMENT约束要求字段为主键或者UNIQUE
 当删除、修改字段的时候,会自动对索引进行维护:
SHOW INDEX FROM book3;
book3	1	multi_bid_bname_binf	1	book_id	A	0			YES	BTREE			YES
book3	1	multi_bid_bname_binf	2	book_name	A	0			YES	BTREE			YES
book3	1	multi_bid_bname_binf	3	info	A	0			YES	BTREE			YES	
ALTER TABLE book3
DROP COLUMN book_name;
SHOW INDEX FROM book3;
book3	1	multi_bid_bname_binf	1	book_id	A	0			YES	BTREE			YES
book3	1	multi_bid_bname_binf	2	info	A	0			YES	BTREE			YES
2 MySQL 8.0 索引新特性
2.1 支持降序索引
 降序索引会以降序存储键值,虽然在语法上mysql4.0就支持索引降序了,但是实际上DESC是被忽略的(使用反向扫描来实现降序),直到mysql 8.0 才开始真正支持降序索引(仅限于innoDB存储引擎)
	使用降序索引意义重大,如一个查询,需要对多个列进行排序,而且顺序要求不一致,那么降序索引就能够避免数据库使用额外的文件排序来实现反向扫描,从而提高性能。
 举个栗子,首先在5.0 和 8.0 都创建一张表:
CREATE TABLE ts1 (
	a int,
	b int,
	INDEX idx_a_b(a, b DESC)
)
 然后编写一个存储过程添加一些数据:
DELIMITER //
CREATE PROCEDURE ts_insert()
BEGIN
	DECLARE i INT DEFAULT 1;
	WHILE i < 800
	DO
		INSERT INTO ts1 SELECT RAND() * 80000, RAND() * 80000;
		SET i = i + 1;
	END WHILE;
	COMMIT;
END //
DELIMITER;
 此时按照a升序、b升序检索,查看执行计划:
EXPLAIN SELECT * FROM ts1 ORDER BY a, b
1	SIMPLE	ts1		index		idx_a_b	10		799	100	Using index; Using filesort
可以看到使用了索引和文件排序
 此时按照a升序、b降序检索,查看执行计划:
EXPLAIN SELECT * FROM ts1 ORDER BY a, b DESC
1	SIMPLE	ts1		index		idx_a_b	10		799	100	Using index
可以看到只使用了索引
而5.0版本的mysql则是也会使用文件排序,因为实际存储时仍按照b升序排列的
这里就不演示了
2.2 支持隐藏索引
	使用场景:在MySQL5.7及之前,只能通过显示的方式删除索引,此时如果发现索引删除后出现错误,则又需要再添加创建索引,如果此时表中已经存储了大量的数据或者表本身比较大,则就会消耗过多的资源,操作成本非常高。或者想要验证索引删除后的性能影响。
	功能:Mysql 8.0后支持的隐藏索引,只需要将待删除的索引设置为隐藏索引,查询优化器就不会使用这个索引(哪怕使用force index也不会),确认删除索引不会出错后,再真正删除索引。这种通过设置隐藏索引,再删除索引的方式就是软删除。
主键不能设置为隐藏索引,当表中没有显示的主键,表中的第一个非空索引就会成为隐式主键,也不能设置隐藏索引
创建表的时候直接创建隐藏索引
CREATE TABLE book4 (
book_id INT,
book_name VARCHAR(100),
AUTHORS VARCHAR(100),
info varchar(100),
COMMENT VARCHAR(100),
year_publication YEAR,
INDEX multi_bid_bname_binf(book_id, book_name, info) INVISIBLE
) SHOW INDEX FROM book4

这时候尝试使用索引进行查询:
EXPLAIN SELECT * FROM book4 WHERE book_id = 1

创建表以后隐藏索引
ALTER TABLE book4
ADD UNIQUE INDEX uq_idx_bid(book_id) ALTER TABLE book4
ADD UNIQUE INDEX uq_idx_bname(book_name) INVISIBLE
修改索引可见性
ALTER TABLE book4
ALTER INDEX uq_idx_bname VISIBLE;
注意
索引被隐藏只是查询优化器不可见,但是仍然和正常索引一样是实时更新的,因此索引长时间被隐藏应该删除,避免影像增删改的性能

MySQL(十一)索引的分类和创建原则的更多相关文章
- MySQL 的索引和最左前缀原则
		
这两天看<构建高性能Web站点>这本书,感觉写的真是不错,很多实际项目中会碰到的问题都有所提及,今天看到一个最左前缀原则,以前也听说过,不过一直没搞明白,今天查了下. 通过实例理解单列索引 ...
 - 【Mysql】—— 索引的分类
		
注意:索引是在存储引擎中实现的,也就是说不同的存储引擎,会使用不同的索引.MyISAM和InnoDB存储引擎:只支持BTREE索引,也就是说默认使用BTREE,不能够更换.MEMORY/HEAP存储引 ...
 - Mysql联合索引的最左前缀原则以及b+tree
		
软件版本mysql5.7 根据官网的文档 https://dev.mysql.com/doc/refman/5.7/en/multiple-column-indexes.html 查询条件要符合最左原 ...
 - mysql 复合索引 为什么遵循最左原则
		
1,>mysql :多列索引 https://dev.mysql.com/doc/refman/5.7/en/multiple-column-indexes.html 1>,B+树: h ...
 - MySQL学习----索引的使用
		
一.什么是索引?为什么要建立索引? 索引用于快速找出在某个列中有一特定值的行,不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行,表越大,查询数据所花费的时间就越多,如果表中查询的 ...
 - 【Mysql】索引简介
		
本文口味:番茄炒蛋,预计阅读:10分钟. 博客又停更了两个月,在这期间,对人生和世界多了许多思考.在人生的不同阶段,会对生活和世界有着不一样的认知,而认知的改变也会直接反应在行为模式之中. 对于生活的 ...
 - 来了解一下Mysql索引的相关知识:基础概念、性能影响、索引类型、创建原则、注意事项
		
索引的基础概念索引类似于书籍的目录,要想找到一本书的某个特定主题,需要先查找书的目录,定位对应的页码:存储引擎使用类似的方式进行数据查询,先去索引当中找到对应的值,然后根据匹配的索引找到对应的数据行 ...
 - SQL优化 MySQL版  - 索引分类、创建方式、删除索引、查看索引、SQL性能问题
		
SQL优化 MySQL版 - 索引分类.创建方式.删除索引.查看索引.SQL性能问题 作者 Stanley 罗昊 [转载请注明出处和署名,谢谢!] 索引分类 单值索引 单的意思就是单列的值,比如说有 ...
 - mysql 索引及索引创建原则
		
是什么 索引用于快速的查询某些特殊列的某些行.如果没有索引, MySQL 必须从第一行开始,然后通过搜索整个表来查询有关的行.表越大,查询的成本越大.如果表有了索引的话,那么 MySQL 可以很快的确 ...
 - Mysql的索引调优详解:如何去创建索引以及避免索引失效
		
在正式介绍Mysql调优之前,先补充mysql的两种引擎 mysql逻辑分层 InnoDB:事务优先(适合高并发操作,行锁) MyISAM:性能优先(表锁) 查看使用的引擎: show variabl ...
 
随机推荐
- linux查看所有的用户和组信息
			
1.cat /etc/passwd 查看所有用户 2.cat /etc/passwd|grep 用户名,用于查找某个用户 3.cat /etc/group查看所有组信息 4.cat /etc/g ...
 - 微信小程序——石头剪刀布
			
博客班级 https://edu.cnblogs.com/campus/zjcsxy/SE2020 作业要求 https://edu.cnblogs.com/campus/zjcsxy/SE2020/ ...
 - 基于vue2.0创建vue项目
			
一.安装node环境 1.下载地址为:https://nodejs.org/en/ 2.检查是否安装成功:如果输出版本号,说明我们安装node环境成功 3.为了提高我们的效率,可以使用淘宝的镜像:ht ...
 - 2vue
			
事件 v-on:click="handle" @click="handle" handle创建在methods里 <!DOCTYPE html> & ...
 - FCC 中级算法题   数组扁平化
			
Steamroller 对嵌套的数组进行扁平化处理.你必须考虑到不同层级的嵌套. Array.isArray() 思路: (1)遍历arr,如果arr[i]是数组,就重新调用本函数继续循环,然后和新数 ...
 - logrotate linux 系统日志管理
			
logrotatelogrotate简介 logrorare一定程度上可以简化对会生成大量日志文件的系统的管理.logrotate可以实现自动轮替.删除.压缩和mail日志的功能. 执行命令logro ...
 - 5.3dmax轴相关
			
# 知识点: 转换为可编辑的样条线(spline) chamfer 切角 Fillet 圆角 车削命令 书柜案例2 样条线(从图形到多边形) 1.在平面视图中选择矩形并创建一个矩形,将矩形转化为可编辑 ...
 - 渲染器的实现(1)--《vue.js设计与实现》
			
function renderer(domString, container) { container.innerHTML = domString } let count = ref(1) rende ...
 - linux  安装 jupyter notebook
			
虚拟机使用的是ubuntu系统 直接遇见一个问题 E: 无法获得锁 /var/lib/dpkg/lock - open (11: 资源暂时不可用) E: 无法锁定管理目录(/var/lib/dpkg/ ...
 - virsh虚拟机使用网桥来实现上网
			
使用virsh-install安装虚拟机后,虚拟机不可以上网 第一步:主机上配置网桥 cp ifcfg-eno16777736 /tmp/ cp ifcfg-eno16777736 ifcfg ...