MySQL 8.0 实现了索引的隐藏属性。当然这个特性很多商业数据库早就有了,比如ORACLE,在11g中就实现了。我来介绍下这个小特性。

介绍

INVISIBLE INDEX,不可见索引或者叫隐藏索引。就是对优化器不可见,查询的时候优化器不会把她作为备选。

其实以前要想彻底不可见,只能用开销较大的drop index;现在有了新的方式,可以改变索引的属性,让其不可见,这一操作只更改metadata,开销非常小。

使用场景

我大概描述下有可能使用隐藏索引的场景:

1. 比如,我有张表t1,本来已经有索引idxf1,idxf2,idxf3。我通过数据字典检索到idxf3基本没有使用过,那我是不是可以判断这个索引直接删掉就好了?那如果删掉后突然有新上的业务要大量使用呢?难道我要频繁的drop index/add index吗?这个时候选择开销比较小的隐藏索引就好了。

2. 我的业务只有一个可能每个月固定执行一次的SQL用到这个索引,那选择隐藏索引太合适不过了。

3. 又或者是我想要测试下新建索引对我整个业务的影响程度。如果我直接建新索引,那我既有业务涉及到这个字段的有可能会收到很大影响。那这个时候隐藏索引也是非常合适的。

举例

下面我来简单举例如何使用隐藏索引:

表结构mysql> create table f1 (id serial primary key, f1 int,f2 int );Query OK, 0 rows affected (0.11 sec)

创建两个索引,默认可见。

索引1,mysql> alter table f1 add key idx_f1(f1), add key idx_f2(f2);Query OK, 0 rows affected (0.12 sec)Records: 0  Duplicates: 0  Warnings: 0

索引2,mysql> show create table f1\G*************************** 1. row ***************************       Table: f1Create Table: CREATE TABLE `f1` (  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,  `f1` int(11) DEFAULT NULL,  `f2` int(11) DEFAULT NULL,  PRIMARY KEY (`id`),  UNIQUE KEY `id` (`id`),  KEY `idx_f1` (`f1`),  KEY `idx_f2` (`f2`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci1 row in set (0.00 sec)

简单写个造数据的存储过程。DELIMITER $$

USE`ytt`$$

CREATE PROCEDURE`sp_generate_data_f1`(

IN f_cnt INT

)

BEGIN

DECLARE i,j INT DEFAULT0;

SET@@autocommit=0;

WHILE i

SET i=i+1;

IF j=100THEN

SET j=0;

COMMIT;

ENDIF;

SET j=j+1;

INSERT INTO f1(f1,f2)SELECT CEIL(RAND()*100),CEIL(RAND()*100);

ENDWHILE;

COMMIT;

SET@@autocommit=1;

END$$

DELIMITER;

生成1W条记录mysql> call sp_generate_data_f1(10000);Query OK, 0 rows affected (5.42 sec)

我们把f2列上的索引变为不可见,结果瞬间完成。mysql> alter table f1 alter index idx_f2 invisible;Query OK, 0 rows affected (0.05 sec)Records: 0  Duplicates: 0  Warnings: 0

在看下表结构,此时索引标记为Invisible。mysql> show create table f1 \G*************************** 1. row ***************************       Table: f1Create Table: CREATE TABLE `f1` (  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,  `f1` int(11) DEFAULT NULL,  `f2` int(11) DEFAULT NULL,  PRIMARY KEY (`id`),  UNIQUE KEY `id` (`id`),  KEY `idx_f1` (`f1`),  KEY `idx_f2` (`f2`) /*!80000 INVISIBLE */) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci1 row in set (0.00 sec)

给一条有f2列过滤的SQL, 发现优化器用不到这个索引了。mysql> explain select count(*) from f1 where f2 = 52\G*************************** 1. row ***************************           id: 1  select_type: SIMPLE        table: f1   partitions: NULL         type: ALLpossible_keys: NULL          key: NULL      key_len: NULL          ref: NULL         rows: 9991     filtered: 1.00        Extra: Using where1 row in set, 1 warning (0.00 sec)

用force index 强制使用,直接报错。mysql> explain select count(*) from f1 force index (idx_f2) where f2 = 52\GERROR 1176 (42000): Key 'idx_f2' doesn't exist in table 'f1'

那 MySQL 8.0 的优化器开关里可以告诉它,有的时候可以用隐藏索引。来打开看看。mysql> set @@optimizer_switch = 'use_invisible_indexes=on';Query OK, 0 rows affected (0.00 sec)

那这条SQL 现在可以用idx_f2了。mysql> explain select count(*) from f1 where f2 = 52\G*************************** 1. row ***************************           id: 1  select_type: SIMPLE        table: f1   partitions: NULL         type: refpossible_keys: idx_f2          key: idx_f2      key_len: 5          ref: const         rows: 121     filtered: 100.00        Extra: Using index1 row in set, 1 warning (0.00 sec)

总结

INVISIBLE INDEX 的确是一个很有用的小特性,给索引增加了第三个额外的开关选项。想要了解更多的建议阅读MySQL手册。

mysql force index报错_新特性解读 | MySQL 8.0 索引特性4-不可见索引相关推荐

  1. mysql 唯一性约束报错_怪异的MySQL Online DDL报错Duplicate entry

    今天线上执行Online DDL的时候发现一个奇怪的报错,觉得比较意义,遂整理如下.线上数据库版本:percona server 5.7.14 报错现场:每次执行的时候重复报错记录都不一样 mysql ...

  2. mysql建立存储过程报错_【松勤教育】MySQL如何创建存储过程

    工作中有时候需要自己去创建存储过程,然后调用存储去获得一些数据等,接下来就给大家介绍下MySQL如何创建存储过程. 语法: CREATE PROCEDURE 存储程名([[IN|OUT|INOUT] ...

  3. 打开mysql3306库报错_允许远程链接mysql,开放3306端口

    首先查看端口是否打开 netstat -an|grep 3306 此图为开启3306端口的截图,之前显示为. . . 127.0.0.1:3306 . . . 打开mysql配置文件vi /etc/m ...

  4. mysql严格模式 报错_代码一上传服务器就报错-尝试开启 MySQL 严格模式

    先前遇到过一个非常奇怪的问题,写 MySQL 数据库的 web 程序的时候,在自己本机环境下跑的好好的,一上传到远程服务器环境上,就各种报错,各种异常.一般来讲,问题的根源多半是环境差异导致的,且大概 ...

  5. cmd mysql 报错_客户端cmd打开mysql,执行插入中文报错或插入中文乱码解决方案

    最近在制作一个安装包,需要安装的时候执行mysql脚本儿,做了一个批处理,但是发现总是执行到 插入中文的时候报错,或者插入中文是乱码. 网上查了好多资料,说是把编码改成GBK什么的,终究还是不成功. ...

  6. 打开mysql 的时候报错_关于mysql的启动报错处理

    昨天使用rpm安装了一个mysql最新版本,在安装的时候因为系统里面自带了mysql5.1的版本.所以我在安装mysql5.5的时候一直报错,故使用yum -y remove mysql*将老版本的安 ...

  7. mysql outer join报错_千与千寻-MySQL联结join

    MySQL的联查包括外联结,內联结,自然联结,cross联结等等. 1.cross join cross join是对两个表执行笛卡尔运算,显示所有两个表的组合返回m*n行.它可以省略掉cross,或 ...

  8. mysql server安装报错_安装VtigerCRM报错:MySQL Server should be configured with

    安装报错提示如下: MySQL Server should be configured with: sql_mode = ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREA ...

  9. mysql语句delete报错_「delete语句」MySQL——DELETE语句中的坑 - seo实验室

    delete语句 在网上搜索了一个mysql数据库删除重复数据的sql,原文是这样的: DELETE FROM people WHERE peopleName IN ( SELECT peopleNa ...

最新文章

  1. java单链表输出_数据结构基础------1.线性表之单链表的创建与输出方法(Java版)...
  2. go的http服务报错accept4: too many open files
  3. python slenium 中CSS定位
  4. 【计算机网络】TCP/IP 模型与OSI参考模型的比较
  5. mysql datetime timestamp 索引_MYSQL中时间类型底层存储,DATETIME ,TIMESTAMP,INT 如何选择?...
  6. XHTML的使用规范
  7. iOS开发隐藏tabBar的问题
  8. of介词短语作定语_介词短语作定语时的译法
  9. centos6.5 vncserver安装与配置
  10. 20071020ー胡小蝶
  11. Linux下编写C语言
  12. android项目中在webview中打开pdf
  13. 关于企业微信中开发第三方应用遇到的退出问题
  14. 使用adb命令清除预装内置的第三方app
  15. 在Ubuntu KyLin 16.04上安装g2o
  16. 乔布斯遗失16年采访:A级人才的自尊心,不需要呵护
  17. 四辆小车,每辆车加满油可以走一公里,问怎么能让一辆小车走最远
  18. php爬虫抓取信息及反爬虫相关
  19. 探索职场真我---“DISC测评”
  20. 选型宝访谈:微软CRM X 全球顶尖AI技术=?

热门文章

  1. linux反序列化漏洞,思科多个产品Java反序列化漏洞(CVE-2015-6420)
  2. linux重装hal服务安装,linux ubuntu 安装微信客户端
  3. Python程序输入一个字符串并查找总数的大写和小写字母
  4. MySQL 基础模块的面试题总结
  5. Windows 7 设置devenv.exe启动版本
  6. openssl ssl_write 写错误
  7. 如何发布.Net MVC 网站项目(攻略集锦)
  8. linux系统启动自动启动,linux系统下的自动启动
  9. 计算机的iscsi配置,我们将了解如何设置自己的支持iscsi配置的存储节点
  10. 用java编写奖金税率_企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%_java企业利润提成计算代码...