MySQL高级讲座篇之:如何利用MySQL 8.0的`Invisible Indexes`进行在线索引的创建和删除?

各位观众老爷,大家好!我是你们的老朋友,今天咱们来聊聊MySQL 8.0 里的一个超级实用的小技巧——Invisible Indexes(隐形索引)。这玩意儿,简直是 DBA 和开发者的福音,特别是当你需要在生产环境搞事情,又怕影响在线业务的时候,它能帮上大忙。

咱们今天就来好好唠唠,怎么利用Invisible Indexes 来实现优雅的在线索引创建和删除,保证咱们的数据库在折腾的时候,依然能稳如老狗。

开场白:索引,数据库的加速器,但也是风险点

索引,大家都知道,是数据库里用来加速查询的利器。就像给书加个目录,查东西嗖嗖的。但是,索引也不是越多越好,它会占用空间,还会影响写入性能。而且,在线创建或者删除索引,弄不好就容易锁表,导致业务卡顿,甚至直接崩盘。

所以,如何安全、平稳地创建和删除索引,一直是数据库管理员们头疼的问题。MySQL 8.0 的 Invisible Indexes,就是来解决这个问题的。

Invisible Indexes 是个啥?

简单来说,Invisible Indexes 就是“隐身”的索引。它存在于数据库中,但优化器默认情况下不会使用它。你可以把它想象成一个“潜伏”的索引,只有当你明确告诉优化器可以使用它的时候,它才会发挥作用。

这个特性,给我们带来了极大的灵活性。我们可以先创建一个 Invisible Index,观察它的效果,如果效果好,再让它“现身”;如果效果不好,直接删除,而不用担心影响线上业务。

Invisible Indexes 的优点

  • 在线创建和删除: 这是最大的优点,可以在不锁表的情况下创建和删除索引,减少对线上业务的影响。
  • 测试索引效果: 可以先创建 Invisible Index,观察它的查询计划,评估它的效果,再决定是否启用。
  • 逐步优化: 可以逐步调整索引的定义,例如增加或删除列,观察效果,直到找到最佳的索引方案。
  • 回滚方便: 如果索引效果不好,可以直接删除,或者让它继续“隐身”,而不用担心影响线上业务。

语法和操作

好,咱们来点干货,看看怎么用 Invisible Indexes。

1. 创建 Invisible Index

在创建索引的时候,加上 INVISIBLE 关键字就可以了。

CREATE INDEX idx_name ON table_name (column_name) INVISIBLE;

例如,我们要在 users 表的 email 列上创建一个 Invisible Index:

CREATE INDEX idx_email ON users (email) INVISIBLE;

这条语句执行后,idx_email 索引就创建好了,但是优化器默认不会使用它。

2. 查看索引是否 Invisible

可以通过 SHOW INDEXES 命令查看索引的 Visible 属性。

SHOW INDEXES FROM users WHERE Key_name = 'idx_email';

返回结果中,Visible 列的值如果是 NO,就表示这个索引是 Invisible 的。

或者,你也可以查询 INFORMATION_SCHEMA.STATISTICS 表:

SELECT INDEX_NAME, VISIBLE FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_NAME = 'users' AND INDEX_NAME = 'idx_email';

3. 让 Invisible Index “现身”

要让 Invisible Index “现身”,可以使用 ALTER TABLE 语句,将 VISIBLE 属性设置为 YES

ALTER TABLE users ALTER INDEX idx_email VISIBLE;

执行这条语句后,优化器就可以使用 idx_email 索引了。

4. 让 Visible Index “隐身”

如果想让一个 Visible Index 变成 Invisible 的,也可以使用 ALTER TABLE 语句,将 VISIBLE 属性设置为 NO

ALTER TABLE users ALTER INDEX idx_email INVISIBLE;

执行这条语句后,优化器就不会使用 idx_email 索引了。

5. 删除 Invisible Index

删除 Invisible Index 和删除普通的索引没什么区别,直接使用 DROP INDEX 语句就可以了。

DROP INDEX idx_email ON users;

实战演练:在线创建索引

假设我们有一个 orders 表,数据量很大,现在我们需要在 order_date 列上创建一个索引,以提高查询效率。但是,直接创建索引可能会锁表,影响线上业务。怎么办呢?

我们可以使用 Invisible Indexes 来实现在线创建索引。

步骤 1:创建 Invisible Index

CREATE INDEX idx_order_date ON orders (order_date) INVISIBLE;

这条语句会创建一个 Invisible Index,优化器不会使用它。

步骤 2:观察查询计划

创建索引后,我们可以使用 EXPLAIN 命令来观察查询计划,看看如果使用这个索引,查询效率会有多大的提升。

首先,我们需要设置 optimizer_switch 参数,让优化器可以使用 Invisible Indexes。

SET optimizer_switch = 'use_invisible_indexes=on';

然后,执行 EXPLAIN 命令,看看查询计划。

EXPLAIN SELECT * FROM orders WHERE order_date = '2023-10-26';

如果查询计划中使用了 idx_order_date 索引,就说明这个索引是有用的。

步骤 3:让 Invisible Index “现身”

如果查询计划显示索引有用,我们就可以让它“现身”,让优化器真正使用它。

ALTER TABLE orders ALTER INDEX idx_order_date VISIBLE;

执行这条语句后,优化器就可以使用 idx_order_date 索引了。

步骤 4:观察性能

索引“现身”后,我们需要观察一段时间的性能,看看是否真的提高了查询效率。可以使用各种监控工具来观察数据库的性能指标,例如 QPS、响应时间等。

步骤 5:如果效果不好,让索引再次“隐身”

如果索引的效果不好,甚至影响了写入性能,我们可以让它再次“隐身”。

ALTER TABLE orders ALTER INDEX idx_order_date INVISIBLE;

然后,我们可以尝试调整索引的定义,或者直接删除它。

实战演练:在线删除冗余索引

假设我们发现 users 表上的 idx_name 索引是冗余的,很少被使用,而且还影响了写入性能。我们想删除它,但是又怕误删,影响线上业务。怎么办呢?

我们可以使用 Invisible Indexes 来实现安全删除索引。

步骤 1:让索引“隐身”

ALTER TABLE users ALTER INDEX idx_name INVISIBLE;

这条语句会让 idx_name 索引“隐身”,优化器不会使用它。

步骤 2:观察一段时间

让索引“隐身”后,我们需要观察一段时间,看看是否对线上业务产生了影响。可以使用各种监控工具来观察数据库的性能指标,例如 QPS、响应时间等。

步骤 3:如果没问题,删除索引

如果观察一段时间后,发现线上业务没有受到影响,就可以安全地删除索引了。

DROP INDEX idx_name ON users;

注意事项

  • optimizer_switch 参数: 要让优化器可以使用 Invisible Indexes,需要设置 optimizer_switch 参数:SET optimizer_switch = 'use_invisible_indexes=on';。注意,这个参数是会话级别的,只对当前会话有效。如果你想全局生效,需要修改 MySQL 的配置文件。
  • 监控: 在创建或删除索引后,一定要密切关注数据库的性能指标,确保线上业务不受影响。
  • 测试环境: 在生产环境操作之前,一定要在测试环境进行充分的测试。

总结

Invisible Indexes 是 MySQL 8.0 中一个非常实用的特性,它可以帮助我们安全、平稳地创建和删除索引,减少对线上业务的影响。希望今天的讲座能帮助大家更好地理解和使用这个特性。

常见问题解答 (FAQ)

问题 答案
Invisible Index 会占用空间吗? 会的。Invisible Index 仍然是一个索引,它会占用磁盘空间。
Invisible Index 会影响写入性能吗? 会的。即使索引是 Invisible 的,每次写入操作仍然需要更新索引,所以会对写入性能产生一定的影响。但是,影响通常比 Visible Index 小,因为优化器不会使用它来加速查询。
什么时候应该使用 Invisible Indexes? 当你需要在生产环境创建或删除索引,又担心影响线上业务的时候,可以使用 Invisible Indexes。例如,当你需要创建一个新的索引,但是不确定它是否真的能提高查询效率的时候,可以先创建一个 Invisible Index,观察它的效果,然后再决定是否启用。当你需要删除一个索引,但是不确定它是否真的没有被使用的时候,可以先让它“隐身”,观察一段时间,然后再删除。
所有类型的索引都可以是 Invisible 的吗? 是的,所有类型的索引(包括主键索引、唯一索引、全文索引等)都可以是 Invisible 的。
如何让某个查询强制使用 Invisible Index? 可以使用 FORCE INDEX 提示。例如:SELECT * FROM orders FORCE INDEX (idx_order_date) WHERE order_date = '2023-10-26'; 即使 idx_order_date 是 Invisible 的,这条语句也会强制使用它。 注意: 谨慎使用 FORCE INDEX,因为它会强制优化器使用指定的索引,即使这个索引不是最优的。
Invisible Indexes 可以用于分区表吗? 可以的。Invisible Indexes 可以用于分区表。你需要确保在创建或修改索引时,指定正确的分区。

结束语

好了,今天的讲座就到这里了。希望大家有所收获,以后遇到在线索引的问题,可以淡定地使用 Invisible Indexes 来解决。记住,数据库操作要谨慎,多测试,多观察,才能保证线上业务的稳定运行。

下次再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注