接着上期说,MYSQL 8 的索引的方式相对MYSQL 5.7 有了很多的进步,其中最突出的就是添加的functional indexes , 那么这个功能到底是什么时候开始的有的。
8.013 ,对MYSQL 8.013版本中开始添加了函数索引,下面我们举一个例子
create table function_test (id bigint primary key auto_increment, name varchar(20) not null, birth_day datetime);
mysql> insert into function_test (name,birrth_day) values ('Tim','2018-09-09'); Query OK, 1 row affected (0.01 sec) mysql> insert into function_test (name,birrth_day) values ('Sam','2020-01-09'); Query OK, 1 row affected (0.01 sec) mysql> insert into function_test (name,birrth_day) values ('Pam','2021-01-09'); Query OK, 1 row affected (0.00 sec) Alter table function_test add index month(birrth_day);
实际上我们得到了一个带有函数的索引 CREATE TABLE `function_test` ( `id` bigint NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL, `birrth_day` datetime DEFAULT NULL, PRIMARY KEY (`id`), KEY `month` (`birrth_day`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
explain select birrth_day from function_test where month(birrth_day) = 5; explain select birrth_day from function_test where month(birrth_day) = 5;
基于这个功能,MYSQL的的版本应该是在8.013 版本以上。
而前缀索引是MYSQL独有的功能,但使用时有场景的,也就是首先添加前缀索引的额类型是字符类型,通过字段前部分的字段的值就可以明细查找数据,其主要的目的就是减少索引字节的同时,还能提高效率。
我们举例
create table prefix_test (id bigint primary key auto_increment,name varchar(20) not null, type_comments varchar(2000));
mysql> insert into prefix_test (name,type_comments) values ('Tim','1_我不喜欢'); Query OK, 1 row affected (0.01 sec) mysql> insert into prefix_test (name,type_comments) values ('Sam','3_我很喜欢'); Query OK, 1 row affected (0.01 sec) mysql> insert into prefix_test (name,type_comments) values ('Semon','2_没感觉'); Query OK, 1 row affected (0.00 sec) mysql> alter table prefix_test add index (type_comments(1)); Query OK, 0 rows affected (0.07 sec) Records: 0 Duplicates: 0 Warnings: 0
explain select name from prefix_test where type_comments like '1%'; 通过上面的例子也可以看出,实际上我们只需要给2000 字符的,中的一个1个字符建立索引,就可以完成某些快速查找的完成。
或者可以通过这样的方式进行GROUP BY 等方式的数据组织等。
在这些过后就是MYSQL 的隐藏索引,这个并不是一个新的功能,在其他数据库也有类似的索引类型,实际上隐藏索引是针对某些查询来验证索引的有效性,并且让他上线或者下线的功能。
mysql> mysql> alter table prefix_test add index (type_comments(1)) invisible; Query OK, 0 rows affected (0.08 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> show create table prefix_test; CREATE TABLE `prefix_test` ( `id` bigint NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL, `type_comments` varchar(2000) DEFAULT NULL, PRIMARY KEY (`id`), KEY `type_comments` (`type_comments`(1)) /*!80000 INVISIBLE */ ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci | mysql> explain select name from prefix_test where type_comments like '1%'; | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | | 1 | SIMPLE | prefix_test | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 33.33 | Using where | 1 row in set, 1 warning (0.00 sec) 上面的图中可以展示出虽然建立了新的索引但是invisible 的状态是无法使用的。如果要是要使用可以立即让他进入到 visible的状态。
最后是hash 索引,在上一篇中提到了自己建立了HASH 的方式解决等值索引中的多个字段建立联合索引,我们下面举一个例子来看看如何操作。
mysql> alter table hash_test add hash_col varchar(20) generated always as (crc32(concat(type1,type2))); Query OK, 0 rows affected (0.03 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> select * from hash_test; ---- ------ ------- ------- ------------ | id | name | type1 | type2 | hash_col | ---- ------ ------- ------- ------------ | 1 | Tim | 10 | 20 | 2249310613 | ---- ------ ------- ------- ------------ 1 row in set (0.00 sec) mysql> insert into hash_test (name,type1,type2) values ('Sam','20','30'); Query OK, 1 row affected (0.00 sec) mysql> select * from hash_test; ---- ------ ------- ------- ------------ | id | name | type1 | type2 | hash_col | ---- ------ ------- ------- ------------ | 1 | Tim | 10 | 20 | 2249310613 | | 2 | Sam | 20 | 30 | 2378129210 | ---- ------ ------- ------- ------------ 2 rows in set (0.00 sec)
下面我们就可以给hash 的虚拟字段建立索引
那么下次我们下次在查询的时候,就可以直接使用hash_col 来作为查找的索引字段,而不再关心ytype1 type2 如果有50个字段要建立索引,那么也可以不管,就一个字段可以表达N 个字段的值,这样查询速度快,同时你的索引任何时刻只有一个,空间效率的问题都解决了。