MySQL 8.0 虽然发布很久了,但可能大家都停留在 5.7.x,甚至更老,其实 MySQL 8.0 新增了许多重磅新特性,比如栈长今天要介绍的 "隐藏索引" 或者 "不可见索引"。

隐藏索引是什么鬼?

隐藏索引 字面意思就是把索引进行隐藏,即不可见,它不是用来查询优化的,所以它不会被优化器使用到。隐藏索引适用于除主键索引(显示或者隐式设置)之外的索引,意味着主键索引是不能通过任何方式隐藏的。

MySQL 数据库默认创建的索引都是可见的,要显式控制一个索引的可见性,可以在 CREATE TABLE,CREATE INDEX 或 ALTER TABLE 的索引定义命令中使用 VISIBLEINVISIBLE 关键字。

如下面示例所示:

CREATE TABLE javastack (
age INT,
weight INT,
tall INT,
INDEX age_idx (age) INVISIBLE
) ENGINE = InnoDB;
CREATE INDEX weight_idx ON javastack (weight) INVISIBLE;
ALTER TABLE javastack ADD INDEX tall_idx (tall) INVISIBLE;

要变更现有索引的可见性,可以在 ALTER TABLE ... ALTER INDEX 命令中使用 VISIBLEINVISIBLE 关键字。

年龄索引变更为不可见(隐藏):

ALTER TABLE javastack ALTER INDEX age_idx INVISIBLE;

年龄索引变更为可见:

ALTER TABLE javastack ALTER INDEX age_idx VISIBLE;

怎么知道一个表中的索引是可见还是不可见,可以从 INFORMATION_SCHEMA.STATISTICS 表,或者 SHOW INDEX 命令输出中获得。例如:

mysql> SELECT
INDEX_NAME,
IS_VISIBLE
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = 'db1' AND TABLE_NAME = 'javastack';
+------------+------------+
| INDEX_NAME | IS_VISIBLE |
+------------+------------+
| age_idx | YES |
| weight_idx | NO |
| tall_idx | NO |
+------------+------------+

隐藏索引有什么用?

从上面隐藏索引介绍我们知道,隐藏索引可以不被优化器所使用,那么我们可以把某个表的某个索引设置隐藏,然后再测试 SQL 语句的查询性能。

即可以利用隐藏索引快速测试删除索引后对 SQL 查询性能的影响,而无需进行索引删除、重建操作,如果需要该索引,再设置可见就好了,这在大表测试中无疑非常有用,因为对于大表索引的删除和重新添加很耗性能,甚至影响表的正常工作。

隐藏索引设置

如果一个索引被设置成隐藏了,但实际上又需要被优化器所使用,有几种表索引情况缺失对查询造成的影响:

1)SQL 查询语句中包含了索引提示指向不可见索引会发生错误;

2)性能模式数据中显示了受影响 SQL 查询语句的负载增高;

3)SQL 查询语句进行 EXPLIAN 时出现了不同的执行计划;

4)SQL 查询语句出现在了慢查询日志中(之前没有出现);

系统变量 optimizer_switch 的 use_invisible_indexes 标志的值,控制了优化器执行计划构建时是否使用隐藏索引。

如果 use_invisible_indexes 值设置为 off 关闭状态(默认值),优化器默认会忽略隐藏索引,即和加入该参数之前的效果一样。

如果 use_invisible_indexes 值设置为 on 打开状态,隐藏索引仍然保持不可见,但优化器会把隐藏索引加入到执行计划的构建中。

如果想要在某条单个 SQL 查询语句上启用隐藏索引,可以使用 SET_VAR 优化器提示来临时更新 optimizer_switch 的值,如下所示:

mysql> EXPLAIN SELECT /*+ SET_VAR(optimizer_switch = 'use_invisible_indexes=on') */
> age, weight FROM javastack WHERE weight >= 150\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: javastack
partitions: NULL
type: range
possible_keys: weight_idx
key: weight_idx
key_len: 5
ref: NULL
rows: 2
filtered: 100.00
Extra: Using index condition mysql> EXPLAIN SELECT age, weight FROM javastack WHERE weight >= 150\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: javastack
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 5
filtered: 33.33
Extra: Using where

索引的可见性不会影响索引的自身维护,例如,不管索引是可见还是不可见,每次表数据行的更改索引都会更新,并且唯一索引也可防止插入重复数据。

没有显式主键的表如果在 NOT NULL 列上有任何一个唯一索引,则仍可能成为有效的隐式主键。在这种情况下,第一个这样的索引会对表数据行施加与显式主键相同的约束,并且该索引不能设置为不可见。

如以下表的定义:

CREATE TABLE javastack (
age INT NOT NULL,
weight INT NOT NULL,
UNIQUE weight_idx (weight)
) ENGINE = InnoDB;

该表定义不包含任何显式主键,但是 weight 列为 NOT NULL,在该列上创建的唯一索引在数据行上与主键具有相同的约束,并且不能使其不可见:

mysql> ALTER TABLE javastack ALTER INDEX weight_idx INVISIBLE;
ERROR 3522 (HY000): A primary key index cannot be invisible.

假设现在我们将一个显式主键添加到表中:

ALTER TABLE javastack ADD PRIMARY KEY (age);

显式主键不能设置为不可见,此时,weight 列上的唯一索引不再充当隐式主键,因此可以使其设置不可见。

mysql> ALTER TABLE javastack ALTER INDEX weight_idx INVISIBLE;
Query OK, 0 rows affected (0.03 sec)

总结

本文介绍了 MySQL 8.0 中的新特性:隐藏(不可见)索引,这个索引并不是新加的索引类型,而是可以控制索引是否加入到执行计划的构建之中。

在实际生产中也可以利用隐藏索引进行 SQL 语句的性能测试,或者对索引进行逻辑删除,以及索引的灰度发布测试等,用处还是蛮大的。

本次的分享就到这里了,希望对大家有用。觉得不错,在看、转发分享一下哦~

最后,MySQL 系列教程还会继续更新,关注Java技术栈公众号第一时间推送,还可以在公众号菜单中获取历史 MySQL 教程,都是干货。

参考文档:

https://dev.mysql.com/doc/refman/8.0/en/invisible-indexes.html

话说你们用的 MySQL 哪个版本呢?来投票一下!

另外,关注公众号Java技术栈,在后台回复:面试,可以获取我整理的 MySQL 系列面试题和答案,非常齐全。

版权申明:本文系公众号 "Java技术栈" 原创,原创实属不易,转载、引用本文内容请注明出处,禁止抄袭、洗稿,请自重,尊重他人劳动成果和知识产权。

近期热文推荐:

1.Java 15 正式发布, 14 个新特性,刷新你的认知!!

2.终于靠开源项目弄到 IntelliJ IDEA 激活码了,真香!

3.我用 Java 8 写了一段逻辑,同事直呼看不懂,你试试看。。

4.吊打 Tomcat ,Undertow 性能很炸!!

5.《Java开发手册(嵩山版)》最新发布,速速下载!

觉得不错,别忘了随手点赞+转发哦!

牛逼!MySQL 8.0 中的索引可以隐藏了…的更多相关文章

  1. MySQL 8.0 中统计信息直方图的尝试

    直方图是表上某个字段在按照一定百分比和规律采样后的数据分布的一种描述,最重要的作用之一就是根据查询条件,预估符合条件的数据量,为sql执行计划的生成提供重要的依据在MySQL 8.0之前的版本中,My ...

  2. MySQL 并行复制演进及 MySQL 8.0 中基于 WriteSet 的优化

    MySQL 8.0 可以说是MySQL发展历史上里程碑式的一个版本,包括了多个重大更新,目前 Generally Available 版本已经已经发布,正式版本即将发布,在此将介绍8.0版本中引入的一 ...

  3. MySql SqlServer Sqlite中关于索引的创建

    最近要更新Cocon90.Db库,令其ORM创建表时实现索引的添加.因此总结下列常用Sql,供大家学习与参考. 一.SqlServer中创建索引可以这样: ) Create Table Test ( ...

  4. (译)MySQL 8.0实验室---MySQL中的倒序索引(Descending Indexes)

    译者注:MySQL 8.0之前,不管是否指定索引建的排序方式,都会忽略创建索引时候指定的排序方式(语法上不会报错),最终都会创建为ASC方式的索引,在执行查询的时候,只存在forwarded(正向)方 ...

  5. 【Mysql】- Mysql 8.0正式版新亮点

    MySQL 8.0 正式版 8.0.11 已发布,官方表示 MySQL 8 要比 MySQL 5.7 快 2 倍,还带来了大量的改进和更快的性能! 注意:从 MySQL 5.7 升级到 MySQL 8 ...

  6. MySQL 8.0 正式版 8.0.11 发布:比 MySQL 5.7 快 2 倍

    ySQL 8.0 正式版 8.0.11 已发布,官方表示 MySQL 8 要比 MySQL 5.7 快 2 倍,还带来了大量的改进和更快的性能! 注意:从 MySQL 5.7 升级到 MySQL 8. ...

  7. MySQL 8.0 新特性梳理汇总

    一 历史版本发布回顾 从上图可以看出,基本遵循 5+3+3 模式 5---GA发布后,5年 就停止通用常规的更新了(功能不再更新了): 3---企业版的,+3年功能不再更新了: 3 ---完全停止更新 ...

  8. What's New In MySQL 8.0

        由于8.0内有很多C++11特性.需要gcc4.8版本以上.Rhel6系列默认gcc是4.7.在安装gcc6.1之后仍然检查不过. 原因可能是6.1版本不一定高于4.7,暂不讨论.鉴于升级gc ...

  9. MySQL 8.0的关系数据库新特性详解

    前言 MySQL 8.0 当前的最新版本是 8.0.4 rc,估计正式版本出来也快了.本文介绍几个 8.0 在关系数据库方面的主要新特性. 你可能已经知道 MySQL 从版本 5.7 开始提供了 No ...

随机推荐

  1. 【入门必看】不理解「对象」?很可能有致命bug:简单的Python例子告诉你

    简介:越来越多的人要在学习工作中用到『编程』这个工具了,其中很大一部分人用的是Python.大部分人只是做做简单的科研计算.绘图.办公自动化或者爬虫,但-- 这就不需要理解「指针与面向对象」了吗? 在 ...

  2. C#中未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”提供程序

    解决方法 方法一 "设置应用程序池默认属性"/"常规"/"启用32位应用程序",设置为 true. 方法二 生成->配置管理器-> ...

  3. .NET Core AWS S3云存储

    前言 最近有需要用到AWS S3云存储上传附件,这里对利用.NET或.NET Core在调用SDK APi需要注意的一点小问题做个记录,或许能对后续有用到的童鞋提供一点帮助 AWS S3云存储 官方已 ...

  4. 容器编排系统K8s之StatefulSet控制器

    前文我们聊到了k8s的configmap和secret资源的说明和相关使用示例,回顾请参考:https://www.cnblogs.com/qiuhom-1874/p/14194944.html:今天 ...

  5. 记录第一次使用Vivado——以全加器为例子

    从altera转战xilinx,经典的FPGA到ZYNQ系列,第一站就是先熟悉编译软件Vivado.我就直接跳过软件安装部分了,如有疑问,可以在评论区提出来,我看到了就帮你解答. 首先是是打开界面 然 ...

  6. [leetcode]222. Count Complete Tree Nodes完全二叉树的节点数

    /* 满二叉树的特点是2^n-1,对于完全二叉树,一个node如果左右子树深度相同,那么 是一个满二叉树.如果不是,那就把node算上,继续往下看,下边的可能是满二叉树 由于完全二叉树中有一些子满二叉 ...

  7. CI持续集成理论知识

    (1)什么是CI What is CI? CI就是持续集成,持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成.每次集成都通过 ...

  8. 高并发之wait notify notifyAll原理详解

    public class WaitTest { public void testWait(){ System.out.println("Start-----"); try { wa ...

  9. 技术基础 | 监测Apache Cassandra的简明方式——MCAC

    点击这里在GitHub上访问我们,以便深入了解DataStax的开源项目--Apache Cassandra指标收集器(Metric Collector for Apache Cassandra, o ...

  10. 远程分支删除后,git branch -a还能看到的解决方法

    详情https://www.cnblogs.com/wangiqngpei557/p/6058115.html 大家在删除远程分支后 git branch -a 还是可以看到已删除的远程分支,时间一长 ...