美文网首页
mysql8.0——索引优化

mysql8.0——索引优化

作者: 0b19e507ac0c | 来源:发表于2019-06-22 23:04 被阅读0次

在8.0中新增了三种索引类型:隐藏索引、降序索引、函数索引

1、隐藏索引:

含义:mysq8.0开始支持隐藏索引,不可见索引。

特点:不会被优化器所使用,但仍然需要进行维护。

应用场景:软删除、灰度发布。

      软删除: 需要进行索引的删除时,现在只能删除后查看效果,但是删除后发现索引不应该被删除,那只能再创建出来,这个过程是非常耗性能的。这时我们可以使用隐藏索引,先设置为隐藏,等确认删除没有影响之后再进行真正的删除。

使用:

创建隐藏索引的关键字是invisible, 在正常创建索引的最后加上invisible字段即可。

这里我们完整的创建一张表,

create table test_hidden_index(i int, j int);   // 创建一张表,表里有 i 和 j 两个字段

create index idx_i on test_hidden_index(i);                            // 创建一个正常的索引

create index idx_j on test_hidden_index(j) invisible; // 使用invisible关键字创建一个隐藏索引 

show index from test_hidden_index \G            // 这时我们查看一下索引的情况

查看索引的情况

这时我们看到了Visible对应的值分别是 yes 和 no,这里就代表这是否是隐藏索引。

那么我们接下来使用explain 看一下当我们使用i和j分别作为where条件时,索引的使用情况

explain

结论很明显,隐藏索引不可用。

我们知道在mysql5.X中引入了优化器开关选项,同理我们的是否可以使用隐藏索引进行查询也是可以配置的,接下来我们查看一下对应的配置

select @@optimizer_switch \G

optimizer_switch

这里我们只关心use_invisible_indexes的设置,这里是off,下面我们在当前回话中把这个开关打开

set session optimizer_switch = "use_invisible_indexes=on";

这时我们在进行刚才的explain就会发现隐藏索引也可以被正常的使用。

最后我们来我们尝试进行隐藏索引和正常索引的切换

alter table test_hidden_index alter index idx_j visible;  // 设置成非隐藏索引

alter table test_hidden_index alter index idx_j invisible;  // 设置成隐藏索引

关于隐藏索引还需要注意的是,主键不能设置为隐藏索引,这里就不进行演示了。


二、降序索引

mysql8.0开始真正支持降序索引,之前也可以创建降序索引,但是他创建的实际还是升序索引。

只有InnoDB存储引擎支持降序索引,只支持BTREE降序索引。

不再对GROUP BY操作进行隐式排序。

具体使用:

首先我们创建一个包含降序索引的表: create table test_sort_index (c1 int, c2 int, index idx_1(c1 asc, c2 desc));

降序索引

这时我们发现在C2后面跟着desc,代表这一列是降序的,在8.0之前是不会这样显示的,感兴趣的同学可以自己做做实验。

接下来我们使用对应的sql进行这个索引的验证。

explain select * from test_sort_index order by c1,c2 desc \G // 跟创建索引的顺序一样

没有filesort

这时我们发现它可以使用索引,并且没有文件排序。如果在8.0之前,索引也是可以正常使用的,但是会多一步Using filesort,这里我们不对8.0之前进行演示了,但是我们可以使用这样一个sql模拟一下效果。

explain select * from test_sort_index order by c1 DESC ,c2 desc \G // 证明filesort的存在

包含文件排序

那么问题来了,当我们使用索引组合完全相反的查询条件会是什么效果呢?即c1 desc c2 asc

explain select * from test_sort_index order by c1 DESC ,c2 asc \G 

backward index scan

这时我们发现对了一个反向索引扫描的操作,也能证明B+树的叶子节点是使用的双向链表

不再对GROUP BY操作进行隐式排序这里就不演示了。


三、函数索引(有用)

mysql8.0.13开始支持在函数索引中使用函数(表达式)的值

支持降序索引,支持json数据的索引。

函数索引基于虚拟列功能实现的。

使用:

create table test_function_index (c1 varchar(10), c2 varchar(10)); // 首先我们创建一张测试表

create index idx_1 on test_function_index(c1); // 给c1创建一个普通索引

create index idx_2 on test_function_index( (UPPER(c2)) ); // 创建一个upper的函数索引

接下来我们看一下索引的情况

大家如果对innodb的索引结构了解就会清楚,针对我们上述创建的表,在聚集索引这个树可能没有的数据,可以在辅助索引的树种维护。往大了想,可以有一张上千个字段的表,然后我们需要的数据创建出来辅助索引,并且可以对原始数据进行一些数据的加工转化。

当我们使用upper函数的时候进行操作,明显c2会有效,如下图

json索引:

create table test_json_index(data json, index((CAST(data->>'$.name' as char(30)))));    // cast是类型转换,也就是说把data中的name列转换成一个char(30)的列   ->>一个新的运算符。

创建了上述的索引后,当我们使用的时候也是需要使用这个表达式进行查询,

explain select * from test_json_index where CAST(data->>'$.name' as char(30)) = '' \G

对于这种函数索引,我们可以再旧版本中使用虚拟函数列实现对应的效果(当然是不考虑性能的前提下)

alter table test_virtual_function_index add column c3 varchar(10) generated always as (upper(c1));

create index idx_3 on  test_virtual_function_index (c3)

explain select * from test_virtual_function_index where upper(c1) = 'a' \G

相关文章

网友评论

      本文标题:mysql8.0——索引优化

      本文链接:https://www.haomeiwen.com/subject/qlxbqctx.html