详解MySQL 8.0 之不可见索引
作者:用户1278550 发布时间:2024-01-22 17:41:46
言
MySQL 8.0 从第一版release 到现在已经走过了4个年头了,8.0版本在功能和代码上做了相当大的改进和重构。和DBA圈子里的朋友交流,大部分还是5.6 ,5.7的版本,少量的走的比较靠前采用了MySQL 8.0。为了紧追数据库发展的步伐,能够尽早享受技术红利,我们准备将MySQL 8.0引入到有赞的数据库体系。
落地之前 我们会对MySQL 8.0的新特性和功能,配置参数,升级方式,兼容性等等做一系列的学习和测试。以后陆陆续续会发布文章出来。本文算是MySQL 8.0新特性学习的第一篇吧,聊聊 不可见索引。
不可见索引
不可见索引中的不可见是针对优化器而言的,优化器在做执行计划分析的时候(默认情况下)是会忽略设置了不可见属性的索引。
为什么是默认情况下,如果 optimizer_switch设置use_invisible_indexes=ON 是可以继续使用不可见索引。
话不多说,我们先测试几个例子
如何设置不可见索引
我们可以通过带上关键字VISIBLE|INVISIBLE的create table,create index,alter table 设置索引的可见性。
mysql> create table t1 (i int,
> j int,
> k int,
> index i_idx (i) invisible) engine=innodb;
Query OK, 0 rows affected (0.41 sec)
mysql> create index j_idx on t1 (j) invisible;
Query OK, 0 rows affected (0.19 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> alter table t1 add index k_idx (k) invisible;
Query OK, 0 rows affected (0.10 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> select index_name,is_visible from information_schema.statistics where table_schema='test' and table_name='t1';
+------------+------------+
| INDEX_NAME | IS_VISIBLE |
+------------+------------+
| i_idx | NO |
| j_idx | NO |
| k_idx | NO |
+------------+------------+
3 rows in set (0.01 sec)
mysql> alter table t1 alter index i_idx visible;
Query OK, 0 rows affected (0.06 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> select index_name,is_visible from information_schema.statistics where table_schema='test' and table_name='t1';
+------------+------------+
| INDEX_NAME | IS_VISIBLE |
+------------+------------+
| i_idx | YES |
| j_idx | NO |
| k_idx | NO |
+------------+------------+
3 rows in set (0.00 sec)
不可见索引的作用
面对历史遗留的一大堆索引,经过数轮新老交替开发和DBA估计都不敢直接将索引删除,尤其是遇到比如大于100G的大表,直接删除索引会提升数据库的稳定性风险。
有了不可见索引的特性,DBA可以一边设置索引为不可见,一边观察数据库的慢查询记录和thread running 状态。如果数据库长时间没有相关慢查询 ,thread_running比较稳定,就可以下线该索引。反之,则可以迅速将索引设置为可见,恢复业务访问。
Invisible Indexes 是 server 层的特性,和引擎无关,因此所有引擎(InnoDB, TokuDB, MyISAM, etc.)都可以使用。
设置完不可见索引,执行计划无法使用索引
mysql> show create table t2 \G
*************************** 1. row ***************************
Table: t2
Create Table: CREATE TABLE `t2` (
`i` int NOT NULL AUTO_INCREMENT,
`j` int NOT NULL,
PRIMARY KEY (`i`),
UNIQUE KEY `j_idx` (`j`) /*!80000 INVISIBLE */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.01 sec)
mysql> insert into t2(j) values(1),(2),(3),(4),(5),(6),(7);
Query OK, 7 rows affected (0.04 sec)
Records: 7 Duplicates: 0 Warnings: 0
mysql> explain select * from t2 where j=3\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t2
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 7
filtered: 14.29
Extra: Using where
1 row in set, 1 warning (0.01 sec)
mysql> alter table t2 alter index j_idx visible;
Query OK, 0 rows affected (0.08 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> explain select * from t2 where j=3\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t2
partitions: NULL
type: const
possible_keys: j_idx
key: j_idx
key_len: 4
ref: const
rows: 1
filtered: 100.00
Extra: Using index
1 row in set, 1 warning (0.01 sec)
使用不可见索引的注意事项
The feature applies to indexes other than primary keys (either explicit or implicit).
不可见索引是针对非主键索引的。主键不能设置为不可见,这里的 主键 包括显式的主键或者隐式主键(不存在主键时,被提升为主键的唯一索引) ,我们可以用下面的例子展示该规则。
mysql> create table t2 (
>i int not null,
>j int not null ,
>unique j_idx (j)
>) ENGINE = InnoDB;
Query OK, 0 rows affected (0.16 sec)
mysql> select index_name,is_visible from information_schema.statistics where table_schema='test' and table_name='t2';
+------------+------------+
| INDEX_NAME | IS_VISIBLE |
+------------+------------+
| j_idx | YES |
+------------+------------+
1 row in set (0.00 sec)
### 没有主键的情况下,唯一键被当做隐式主键,不能设置 不可见。
mysql> alter table t2 alter index j_idx invisible;
ERROR 3522 (HY000): A primary key index cannot be invisible
mysql>
mysql> alter table t2 add primary key (i);
Query OK, 0 rows affected (0.44 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> select index_name,is_visible from information_schema.statistics where table_schema='test' and table_name='t2';
+------------+------------+
| INDEX_NAME | IS_VISIBLE |
+------------+------------+
| j_idx | YES |
| PRIMARY | YES |
+------------+------------+
2 rows in set (0.01 sec)
mysql> alter table t2 alter index j_idx invisible;
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> select index_name,is_visible from information_schema.statistics where table_schema='test' and table_name='t2';
+------------+------------+
| INDEX_NAME | IS_VISIBLE |
+------------+------------+
| j_idx | NO |
| PRIMARY | YES |
+------------+------------+
2 rows in set (0.01 sec)
force /ignore index(index_name) 不能访问不可见索引,否则报错。
mysql> select * from t2 force index(j_idx) where j=3;
ERROR 1176 (42000): Key 'j_idx' doesn't exist in table 't2'
设置索引为不可见需要获取MDL锁,遇到长事务会引发数据库抖动
唯一索引被设置为不可见,不代表索引本身唯一性的约束失效
mysql> select * from t2;
+---+----+
| i | j |
+---+----+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
| 8 | 11 |
+---+----+
8 rows in set (0.00 sec)
mysql> insert into t2(j) values(11);
ERROR 1062 (23000): Duplicate entry '11' for key 't2.j_idx'
小结
其实没啥说的,祝大家用的愉快。
-The End-
来源:https://cloud.tencent.com/developer/article/1638494


猜你喜欢
- 前言最近碰到了照片识别的场景,正好使用了face_recognition项目,给大家分享分享。face_recognition项目能做的很多
- 今天我给大家分享的是在不刷新页面的前提下,使用PHP+jQuery+Ajax实现多图片上传的效果。用户只需要点击选择要上传的图片,然后图片自
- 在jupyternotebook下导入自己写的模块,有两点需要注意:1.要将自己写的模块编程xxx.py的形式,而不是.ipynb文件2.当
- 因工作需要,要将存放在sql server数据库中的数据全部导入到mysql数据库中,在网上搜集相关资料,找到两种方法,现在分别谈谈对他们的
- 写在前面机器学习强基计划聚焦深度和广度,加深对机器学习模型的理解与应用。“深”在详细推导算法模型背后
- python的列表很重要,学习到后面你会发现使用的地方真的太多了。最近在写一些小项目时经常用到列表,有时其中的方法还会忘哎!所以为了复习写下
- 基于spring boot开发的微服务应用,与MyBatis如何集成?集成方法可行的方法有:1.基于XML或者Java Config,构建必
- mysql 获取规定时间段内的统计数据按年统计SELECT count(*), DATE_FORMAT(orde
- 在神经网络计算过程中,经常会遇到需要将矩阵中的某些元素取出并且单独进行计算的步骤(例如MLE,Attention等操作)。那么在 tenso
- 聚类今天说K-means聚类算法,但是必须要先理解聚类和分类的区别,很多业务人员在日常分析时候不是很严谨,混为一谈,其实二者有本质的区别。分
- Python 能做很多无聊,但有意思的事情,例如接下来的一些案例。以下程序,不要发代码,要不实现不了你整蛊的目的。要打包成一个 exe 程序
- 在数据库中有时我们可能需要对一些数据进行处理,例如四舍五入、直接舍去后面的几位等,其实很简单,都是有现成的函数,我们只需要套用就行了:sel
- 1、向List中添加元素的方法1.1 Python append()方法添加元素append() 方法用于在列表的末尾追加元素,该方法的语法
- 如何把imagenet预训练的模型,输入层的通道数随心所欲的修改,从而来适应自己的任务#增加一个通道w = layers[0].weight
- 上面两个简单的Sql,我们从表面理解,查询的最终结果应该是一样的,但实际结果却和我们想象的不一样第一条sql查询的结果有一条数据第二条sql
- adonet基础示例分享using System;using System.Collections.Generic;using System
- mechanize是对urllib2的部分功能的替换,能够更好的模拟浏览器行为,在web访问控制方面做得更全面。结合beauti
- 一、Sql Server中的日期与时间函数 1. 当前系统日期、时间 select getdate() 2. dateadd 在向指定日期加
- javascript是种脚本语言,浏览器下载到哪儿就会执行到哪儿,这种特性会为编程提供方便,但也容易使程序过于凌乱,支离破碎。 js从功能上
- 什么是合并多行字符串(连接字符串)呢,例如: SQL> desc test; Name Type Nullable Default C