PART1. 索引简介

索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可提高数据库中特定数据的查询速度。

1. 索引的含义和特点

索引是一个单独的、存储在磁盘上的数据库结构,包含着对数据库表里所有记录的引用指针。使用索引可以快速找出在某个或多个列中有一特定值的行,所有MySQL列类型都可以被索引,对相关列使用索引是提高查询操作速度的最佳途径。

索引时在存储引擎中实现的,因此,每种存储引擎的索引都不一定完全相同,并且每种存储引擎也不一定支持所有索引类型。根据存储引擎定义每个表的最大索引数和最大索引长度。所有存储引擎支持每个表至少16个索引,总索引长度至少为256字节。大多数存储引擎有更高的限制。MySQL中索引的存储类型有两种,即BTREE和HASH,具体和表的存储引擎有关;MyISAM和InnoDB储存引擎只支持BTREE索引;MEMORY/HEAP存储引擎可以支持HASH和BTREE索引。

索引的优点主要有以下几点:

(1)通过创建唯一索引,可以保证数据库表中每一行数据的唯一性。

(2)可以大大加快数据的查询速度,这也是创建索引的主要原因。

(3)在实现数据的参考完整性方面,可以加速表和表之间的连接。

(4)在使用分组和排序子句进行数据查询时,也可以显著减少查询中分组和排序的时间。

增加索引也有许多不利的方面,主要表现在如下几个方面:

(1)创建索引和维护索引要耗费时间,并且随着数据量的增加所耗费的时间也会增加。

(2)索引需要占磁盘空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果有大量的索引,索引文件可能比数据文件更快达到最大文件尺寸。

(3)当对表中的数据进行增加、删除和修改的时候,索引也要动态地维护,这样就降低了数据的维护速度。

2. 索引的分类

MySQL的索引可以分为以下几类:

1. 普通索引和唯一索引

普通索引是MySQL中的基本索引类型,允许在定义索引的列中插入重复值和空值。

唯一索引要求索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。主键索引是一种特殊的唯一索引,不允许有空值。

2. 单列索引和组合索引

单列索引即一个索引只包含单个列,一个表可以有多个单列索引。

组合索引是指在表的多个字段组合上创建的索引,只有在查询条件中使用了这些字段的左边字段时,索引才会被使用。使用组合索引时遵循最左前缀集合。

3. 全文索引

全文索引类型为FULLTEXT,在定义索引的列上支持值的全文查找,允许在这些索引列中插入重复值和空值。全文索引可以在CHAR、VARCHAR或者TEXT类型的列上创建。MySQL中只有MyISAM存储引擎支持全文索引。

4. 空间索引

空间索引是对空间数据类型的字段建立的索引,MySQL中的空间数据类型有4种,分别是GEOMETRY、POINT、LINESTRING和POLYGON。MySQL使用SPATIAL关键字进行扩展,使得能够用创建正规索引类似的语法创建空间索引。创建空间索引的列,必须将其声明为NOT NULL,空间索引只能在存储引擎为MyISAM的表中创建。

3. 索引的设计原则

索引设计不合理或者缺少索引都会对数据库和引用程序的性能造成障碍。高效的索引对于获得良好的性能非常重要。设计索引时,应该考虑以下准则:

(1)索引并非越多越好,一个表中如有大量的索引,不仅占用磁盘空间,还会影响INSERT、DELETE、UPDATE等语句的性能,因为在表中的数据更改时,索引也会进行调整和更新。

(2)避免对经常更新的表进行过多的索引,并且索引中的列要尽可能少。应该经常用于查询的字段创建索引,但要避免添加不必要的字段。

(3)数据量小的表最好不要使用索引,由于数据较少,查询花费的时间可能要比遍历索引的时间要短,索引可能不会产生优化结果。

(4)在条件表达式中经常用到的不同值较多的列上建立索引,在不同值很少的列上不要建立索引。比如在学生表的“性别”字段上只有“男”与“女”两个不同值,因此就无须建立索引,如果建立索引不但不会提高查询效率,反而会严重降低数据更新速度。

(5)当唯一性时某种数据本身的特征时,指定唯一索引需能确保定义的列的数据完整性,以提高查询速度。

(6)在频率进行排序或分组(即进行group by 或 order by操作)的列上建立索引,如果待排序的列有多个,可以在这些列上建立组合索引。

PART2. 创建索引

MySQL支持多种方法在单个或多个列上创建索引:

在创建表的定义语句CREATE TABLE中指定索引列

使用ALTER TABLE语句在存在的表上创建索引

使用CREATE INDEX语句在已存在的表上添加索引

1. 创建表的时候创建索引

使用CREATE TABLE创建表时,除了可以定义列的数据类型,还可以定义主键约束,外键约束或者唯一性约束,而不论创建哪种约束,在定义约束的同时相当于在指定列上创建了一个索引。创建表时创建索引的基本语法格式如下:

CREATE TABLE table_name [col_name data_type]
[UNIQUE|FULLTEXT|SPATIAL] [index_name] [col_name [length] [ASC|DESC]]

UNIQUE、FULLTEXT和SPATIAL为可选参数,分别表示唯一索引、全文索引和空间索引;INDEX与KEY为同义词,两者作用相同,用来指定创建索引;col_name为需要创建索引的字段列,该列必须从数据表中定义的多个列中选择;index_name 指定索引的名称,为可选参数,如果不指定,MySQL默认col_name为索引值;length为可选参数,表示索引的长度,只有字符串类型的字段才能指定索引长度;ASC或DESC指定升序或者降序的索引值存储。

1. 创建普通索引

最基本的索引类型,没有唯一性之类的限制,其作用只是加快对数据的访问速度。

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)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
SHOW CREATE TABLE book;
# 使用EXPLAIN语句擦好看索引是否正在使用:
EXPLAIN SELECT * FROM book WHERE year_publication=1990;

EXPLAIN语句输出结果的各个行解释如下:

(1)select_type行指定所使用的SELECT查询类型,这里值为SIMPLE,表示简单的SELECT,不使用UNION或子查询。其他可能的取值有PRIMARY、UNION、SUBQUERY等。

(2)table行指定数据库读取的数据表的名字,他们按被读取的先后顺序排序。

(3)type行指定了本数据表与其他数据表之间的关联关系,可能的取值有system、const、eq_ref、ref、range、index和ALL。

(4)possible_keys行给出了MySQL在搜索数据记录时可选用的各个索引。

(5)key行是MySQL实际选用的索引。

(6)key_len行给出索引按字节计算的长度,key_len数值越小,表示越快。

(7)ref行给出了关联关系中另一个数据表里的数据列名。

(8)rows行是MySQL在执行这个查询时预计会以这个数据表里读出的数据行的格式。

(9)Extra行提供了与关联操作有关的信息。

possible_keys和key的值都为year_publication,查询时使用了索引。

2. 创建唯一索引

创建唯一索引的主要原因是减少查询索引列操作的执行时间,尤其是对比比较庞大的数据表。他与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。

CREATE TABLE t1(
id  INT NOT NULL,
name CHAR(30) NOT NULL,
UNIQUE INDEX UniqIdx(id)
)ENGINE=InnoDB DEFAULT CHARSET= utf8mb4;

3. 创建单列索引

单列索引是在数据表中的某一个字段上创建的索引,一个表中可以创建多个单列索引。前面两个例子中创建的索引都为单列索引。

CREATE TABLE t2(id INT NOT NULL,name CHAR(50) NULL,INDEX SingleIdx(name(20)))ENGINE = InnoDB DEFAULT CHARSET=utf8mb4;SHOW CREATE table t2;

成功创建了一个名为'SingleIdx'的单列索引,索引长度为20。

4. 创建组合索引

组合索引是在多个字段上创建一个索引。

DROP TABLE IF EXISTS t3;CREATE TABLE t3(id INT(11) NOT NULL,name CHAR(30) NOT NULL,age INT(11) NOT NULL,info VARCHAR(255),INDEX MultiIdx(id, name, age))ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;SHOW CREATE TABLE t3;

id、name和age字段上已经成功建立了一个名为MultiIdx的组合索引。

组合索引可起几个索引的作用,但是使用时并不是随便查询哪个字段都可以使用索引,而是遵从“最左前缀”:利用索引中最左边的列集来匹配行,这样的列集称为“最左前缀”。

这里由id、name和age 3 个字段构成的索引,索引行中按id、name、age的顺序存放,索引可以搜索(id,name,age)、(id,name)或id 字段组合。如果列不构成索引最左面的前缀,那么MySQL不能使用局部索引,如(age)或者(name,age)组合则不能使用索引查询:

 例如(age)或者(name,age)组合则不能使用索引查询。

此时possible_keys 和 key 值为NULL,并没有使用在t3表中创建的索引进行查询。

5. 创建全文索引

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

全文索引非常适合于大型数据集,对于小的数据集,它的作用比较小。

6. 创建空间索引

空间索引的空间类型的字段必须为非空。

CREATE TABLE places  (
pk INT  PRIMARY KEY,
position POINT NOT  NULL,
name VARCHAR(200));
INSERT INTO places VALUES  (1,  ST_GeomFromText('POINT(63.4269 10.3958)',  0),  'Nidaros Cathedral');
select * from places; select ST_AsText(position) as geometry, ST_X(position) as x,
ST_Y(position) as y,ST_AsGeoJSON(position) as wzxx,
ST_AsText(position) as sydwfw
from places;

2. 在已经存在的表上创建索引

在已经存在的表中创建索引,可以使用ALTER TABLE语句或者CREATE INDEX语句。

1. 使用ALTER TABLE语句创建索引

ALTER TABLE table_name ADD [UNIQUE|FULLTEXT|SPATIAL] [INDEX|KEY]
[index_name] (col_name[length],...) [ASC| DESC]

与创建表时创建索引的语法不同的是,在这里使用了ALTER TABLE和ADD 关键字,ADD表示向表中添加索引。

SHOW INDEX FROM book 

其中各个主要参数的含义为:

(1)Table 表示创建索引的表。

(2)Non_unique 表示索引非唯一,1代表是非唯一索引,0代表唯一索引。

(3)Key_name 表示索引的名称。

(4)Seq_in_index 表示该字段在索引中的位置,单列索引该值为1,组合索引为每个字段在索引定义中的顺序。

(5)Column_name 表示定义索引的列字段。

(6)Sub_part 表示索引的长度。

(7)Null 表示该字段是否能为空值。

(8)Index_type 表示索引类型。

创建普通索引和组合索引:

注意:对长字段添加索引可以限定索引长度。

创建唯一索引:

Non_Unique字段显示0.

创建全文索引:

CREATE TABLE t6(
id INT NOT NULL,
info CHAR(255)
) ENGINE=InnoDB CHARSET=utf8mb4;
ALTER TABLE t6 ADD FULLTEXT INDEX infoFTIdx( info );
SHOW INDEX FROM t6;

创建了名称为infoFTIdx的索引,该索引在info字段上创建,类型为FULLTEXT,允许为空值。

创建空间索引:

CREATE TABLE t7(g GEOMETRY NOT NULL);
ALTER TABLE t7 ADD SPATIAL INDEX spatIdx(g);
SHOW INDEX FROM t7;

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]

PART3. 删除索引

MySQL中删除索引使用ALTER TABLE或者DROP INDEX语句,两者可实现相同的功能,DROP INDEX语句在内部被映射到一个ALTER TABLE语句中。

1. 使用ALTER TABLE删除索引

ALTER TABLE 删除索引的基本语法格式如下:

ALTER TABLE table_name DROP INDEX index_name;

2. 使用DROP INDEX语句删除索引

DROP INDEX 删除索引的基本语法格式如下:

DROP INDEX index_name ON table_name;

注意:删除表中的时,如果要删除的列为索引的组成部分,则该列也会从索引中删除,如果组成索引的所有列都被删除,则整个索引将被删除。

PART4. MySQL8.0 的新特性1——支持降序索引

MySQL8.0

MySQL5.7

MySQL8.0 执行插入随机数据的存储过程如下:

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;;
CALL ts_insert();

MySQL8.0 ORDER BY a, b DESC

执行计划中只扫描5次,没有使用到Using filesort。

MySQL5.7 ORDER BY a,b DESC

执行计划中扫描799次,使用到Using filesort。

MySQL8.0 ORDER BY a DESC, b DESC

执行计划中扫描799次,使用到Using filesort。

MySQL5.0 ORDER BY a DESC, b DESC

执行计划中扫描5次。

注意:Using filesort是MySQL里一种速度比较慢的外部排序,如果能避免是最好的结果。多数情况下,可以通过优化索引来尽量避免出现Using filesort,从而提高数据库执行速度。

注意:降序索引是对查询中特定的排序顺序有效,如果使用不当反而查询效率更低。

PART5. MySQL8.0 的新特性2——统计直方图

MySQL 8.0 实现了统计直方图。利用直方图,用户可以对一张表的一列做数据分布的统计,特别是针对没有索引的字段。这可以帮助查询优化器找到更有的执行计划。

1. 直方图的优点

在数据库中,查询优化器负责将SQL转换成最有效的执行计划。有时候,查询优化器会找不到最优的执行计划,导致花费了更多不必要的时候。造成这种情况的主要原因是,查询优化器有时无法准确地知道以下几个问题的答案:

1)每个表有多少行?

2)每一列有多少不同的值?

3)每一列的数据分布情况如何?

没有统计数据,优化器会假设tm的值是均匀分配的。如何才能使查询优化器知道数据的分布情况呢? 一个解决方法就是在列上建立统计直方图。

直方图能近似获得一列的数据分布情况,从而让数据库知道它含有哪些数据。直方图有多种形式,MySQL支持了两种:等宽直方图(singleton)和等高直方图(equi-height)。直方图的共同点是,他们都将数据分到了一系列的buckets中去。MySQL会自动将数据划到不同的buckets中,也会自动决定创建哪种类型的直方图。

2. 直方图的基本操作

创建直方图的语法格式如下:

ANALYZE TABLE table_name
[UPDATE HISTOGRAM on col_name with N BUCKETS |DROP HISTOGRAM ON clo_name]

buckets的默认值是100。统计直方图的信息存储在数据字典表“column_statistcs”中,可以通过视图information_schema.COLUMN_STATISTICS访问。直方图以灵活的JSON格式存储。ANALYZE TABLE会基于表大小自动判断是否要进行取样操作。ANALYZE TABLE也会基于表中列的数据分布情况以及bucket的数量来决定是否要建立等宽直方图(singleton)还是等高直方图(equi-height)。

创建测试数据表production:

CREATE TABLE production (id INT, tm TIME, count INT);

在数据表production的字段tm上创建直方图,执行语句如下:

SHOW CREATE TABLE production;
ANALYZE TABLE production UPDATE HISTOGRAM ON tm WITH 60 BUCKETS; -- 

buckets的值必须指定,可以设置为1到1024,默认值是100。设置buckets值时,可以先设置低一些,如果没有满足需求,可以再往上增大。

对于不同的数据集合,buckets的值取决于以下几个因素:

1)这列有多少不同的值。

2)数据的分布情况。

3)需要多高的准确性。

在字段tm和字段count上创建直方图:

再次创建直方图时,将会将上一个直方图重写。

删除已经创建的直方图,用DROP HISTOGRAM就可以实现:

ANALYZE TABLE production DROP HISTORGAM ON tm,count;

直方图统计了表中某些字段的数据分布情况,为优化选择高效的执行计划提供参考。直方图与索引有着本质的区别:维护一个索引有代价,每一次的INSERT、UPDATE、DELETE都会需要更新索引,会对性能有一定的影响;而直方图一次创建永不更新,除非明确去更新它,所以不会影响INSERT、UPDATE、DELETE的性能。

建立直方图的时候,MySQL服务器会将所有数据读到内存中,然后在内存中进行操作,包括排序。如果对一个很大的表建立直方图,可能会需要将几百兆的数据都读到内存中。为了规避这种风险,MySQL会根据给定的histogram_generation_max_men_size的值计算该将多少行数据读到内存中。

设置histogram_generation_max_mem_size 值的方法如下:

SET histogram_generation_max_men_size = 10000;

-- end

MySQL8.0 索引相关推荐

  1. MySQL8.0索引新特性:颠覆了我对索引的认知

    欢迎关注方志朋的博客,回复"666"获面试宝典 来源:http://dbapub.cn/ 函数索引 在MySQL8.0之前对条件字段做函数操作.或者做运算都将不会使用字段上的索引, ...

  2. 单图说TDSQL;OceanBase 2.2 事务引擎核心功能;穿云箭2.0版发布;RMAN DUPLICATE配置19C DG;外键上有无索引的影响;MySQL8.0 索引新功能;GaussDB C

    摘要:墨天轮数据库周刊第16期发布啦,每周1次推送本周数据库相关热门资讯.精选文章.干货文档. 热门资讯 1.英国电信企业Virgin Media营销数据库配置错误 导致90万客户信息泄露 [摘要]英 ...

  3. MySQL-8.0.x 新特性之索引页合并

    [背景] 索引的重要是在些不表.在这里我想说的另一个问题:索引和数据一样在innodb中都是以page的形式来组织的,那么问题就来了. 比如果说索引 ix_person_name 的内容只要8个页面就 ...

  4. mysql8添加索引_MySQL8.0新特性-新的索引方式

    三种新的索引方式 1.隐藏索引 MySQL8.0 支持隐藏索引(invisible index),不可见索引 隐藏索引不会被优化器使用,但需要维护. 应用场景:软删除.灰度发布. 软删除:不确定当前索 ...

  5. 数据结构-索引-实验7:索引优化(MySQL-8.0)

    文章目录 数据结构-索引-实验7:索引优化(MySQL-8.0) 一.实验目的及要求 二.实验环境及相关情况(包含使用软件.实验设备.主要仪器及材料等) 1.实验设备: 2.软件系统: 三.实验内容 ...

  6. MySQL8.0新特性——锁读取

    MySQL8.0 InnoDB支持 NOWAIT和SKIP LOCKED选项SELECT ... FOR SHARE以及SELECT ... FOR UPDATE锁定读取语句. NOWAIT如果请求的 ...

  7. MySQL8.0 - 新特性 - 临时表改进

    temptable engine 我们知道UNION, DERIVED TABLE, CTE, 子查询或者distinct order by之类的查询都可能用到临时表来存储中间结果,官方文档中列举了几 ...

  8. MySQL8.0 - 新特性 - Instant Add Column

    MySQL8.0开始对一些DDL操作做了大量的优化,例如原子DDL, 快速DDL(只修改元数据),前者解决了长期以来mysql的一大诟病,后者则提升了dba同学的生活品质 官方文档列出了一些可以快速d ...

  9. mysql 函数索引_MySQL 8.0 索引特性1-函数索引

    函数索引顾名思义就是加给字段加了函数的索引,这里的函数也可以是表达式.所以也叫表达式索引. MySQL 5.7 推出了虚拟列的功能,MySQL8.0的函数索引内部其实也是依据虚拟列来实现的. 我们考虑 ...

最新文章

  1. 10分钟学会使用YOLO及Opencv实现目标检测
  2. 第十六届全国大学生智能车竞赛百度智慧交通竞赛成绩
  3. 数据告诉你,胡歌的微世界
  4. BAT 才不关心币价,19年的5大重点在这里!
  5. PCL点云库法向量显示,vtk错误“no override found for vtkActor”
  6. LINUX(Cumulus Linux白盒交换机)开发基础到提高[1]-Cumulus Linux简介
  7. sql server在执行批处理时出现错误。错误消息为: 目录名无效
  8. mysql之case_mysql存储过程之case语句
  9. MSIL实用指南-比较运算
  10. tableview 的小 点点,
  11. 文档服务器设置密码,文档服务器设置密码
  12. “偷师腾讯”,苹果要分游戏这杯羹!| 畅言
  13. 有趣的算法(八):3分钟看懂选择排序(C语言实现)
  14. 软件工程 - 设计模式学习之策略模式Strategy
  15. 软件需求最佳实践之需求的沟通与分析
  16. 【Jlink驱动无法加载解决办法】
  17. 彻底解决idea maven依赖报红报错问题
  18. 关于在窗体之间传值的问题 C# winform
  19. dell灵越笔记本后盖怎么拆_如何拆卸Dell Inspiron 15 5570笔记本电脑并安装M.2 SSD
  20. Yocto系列讲解[实战篇]44 - bb文件中函数实操演示(2)

热门文章

  1. 夏天能做的小生意,有哪些项目能每月收入一万多?推荐一下
  2. nodeJS exports
  3. 饶少阳:运营商急需网络大数据能力
  4. 金山云区块链:“上云上链、用数赋智” 是数字经济完整的乐章
  5. 程序设计思维与实践Week9 作业 (1/2/智能班)
  6. 转:常见的医学影像数据格式(1)
  7. BIEE 11g学习
  8. 郭士纳的一招妙棋,IBM的一步险棋
  9. 怎么买企业邮箱最省钱,买企业邮箱省钱秘笈!
  10. 特性AttributeUsage