MySQL 8.0有一个称为“隐藏索引”的新功能,它容许快速启用/禁用MySQL Optimizer使用的索引。html
在此分享一些对这个新功能的首次使用经验和想法。mysql
对咱们有什么用?sql
一是若是你想删除一个索引,但又想事先知道效果。你就能够使它对优化程序不可见。这是一个快速的元数据更改,使索引不可见。一旦肯定没有性能降低,就能够真正去删除索引。服务器
关键的一点是,隐藏索引不能供优化器使用,但它仍然存在,并经过写入操做保持最新。即使咱们尝试“FORCE INDEX”,优化器也不会使用它,虽然我认为咱们应该可以在某种程度上强制它。可能会有这样的状况:ide
咱们能够建立一个新的隐形索引,但若是想要测试它,必须使它可见。这意味着全部对应用程序有即时影响的查询都将可以使用它。若是目的只是想测试它,我不认为这是最好的方法,不是全部人的服务器上都有相同的数据大小和真实数据。强制隐藏索引这时候可能会颇有用。性能
你有许多索引,但不肯定哪个未使用。你能够将一个索引更改成不可见,以查看是否存在任何性能降低。若是是,你能够当即更改。测试
你可能有一个特殊状况,只有一个查询能够使用该索引。在这种状况下,隐藏索引多是一个很好的解决方案。优化
怎么建立隐藏索引url
有两个选项。 咱们能够建立一个具备隐藏索引的表,以下所示:spa
CREATE TABLE `t1` ( `i` int(11) DEFAULT NULL, `j` int(11) DEFAULT NULL, `k` int(11) DEFAULT NULL, KEY `i_idx` (`i`), KEY `idx_1` (`i`,`j`,`k`) INVISIBLE ) ENGINE=InnoDB DEFAULT CHARSET=latin1
或者咱们能够使用alter table并将索引更改成隐藏:
ALTER TABLE t1 ALTER INDEX idx_1 INVISIBLE;
怎么使用隐藏索引
若是咱们如今要删除索引,咱们能够将其更改成隐藏。 可是使用“FORCE / USE INDEX”的查询怎么样? 他们是否会抛出一个错误? 若是强制不存在的索引,你会收到错误。 你不会看到隐藏索引的错误。 优化器不会使用它,但知道它存在。
show create table t1 G *************************** 1. row *************************** Table: t1 Create Table: CREATE TABLE `t1` ( `i` int(11) DEFAULT NULL, `j` int(11) DEFAULT NULL, `k` int(11) DEFAULT NULL, KEY `i_idx` (`i`), KEY `idx_1` (`i`,`j`,`k`) ) ENGINE=InnoDB DEFAULT CHARSET=latin11 row in set (0.00 sec) mysql> explain select * from t1 force index(idx_1) where i=1 and j=4; +----+-------------+-------+------------+------+---------------+-------+---------+-------------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+-------+---------+-------------+------+----------+-------------+ | 1 | SIMPLE | t1 | NULL | ref | idx_1 | idx_1 | 10 | const,const | 2 | 100.00 | Using index | +----+-------------+-------+------------+------+---------------+-------+---------+-------------+------+----------+-------------+1 row in set, 1 warning (0.00 sec) mysql> alter table t1 alter index idx_1 invisible; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0mysql> explain select * from t1 force index(idx_1) where i=1 and j=4; +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 16 | 6.25 | Using where | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+1 row in set, 1 warning (0.01 sec) mysql> explain select * from t1 where i=1 and j=4; +----+-------------+-------+------------+------+---------------+-------+---------+-------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+-------+---------+-------+------+----------+-------------+ | 1 | SIMPLE | t1 | NULL | ref | i_idx | i_idx | 5 | const | 2 | 10.00 | Using where | +----+-------------+-------+------------+------+---------------+-------+---------+-------+------+----------+-------------+1 row in set, 1 warning (0.00 sec)
正如你所看到的,若是咱们使用带有隐藏索引的“FORCE INDEX”,MySQL会执行全表扫描。 MySQL不会抛出任何错误,由于索引存在,但它不可见。 即便有另外一个可用的索引,它也将执行全表扫描。 在大型表上,这可能会致使严重的性能问题。 即便MySQL在查询执行期间不抛出任何错误,它也应该会在错误日志中记录一个警告。
结论
我认为隐形索引是一个伟大的新功能,能够对许多人有用。 若是有须要,能够尝试着去使用,而且尝试记录试图使用隐藏索引的查询,说不定会获得一些惊喜。
英文原文:Thoughts on MySQL 8.0's Invisible Indexes
文章转载自 开源中国社区 [http://www.oschina.net]