MySQL高级讲座篇之:MySQL的`Invisible Indexes`与`Online DDL`的协同工作。

各位观众老爷,早上好!我是今天的主讲人,咱们今天聊点儿MySQL里比较有意思的东西:Invisible Indexes(不可见索引)和 Online DDL(在线数据定义语言)的协同工作。

先来个开胃小菜,大家有没有遇到过这种情况:数据库里索引一大堆,感觉每个都像有用,但又不敢轻易删,万一删错了线上血崩怎么办? 或者,想加个新索引,又怕锁表影响业务,只能等到半夜三更偷偷摸摸地搞?

别慌,MySQL早就为大家考虑到了这些问题, Invisible Indexes 和 Online DDL 就是解决这些痛点的两大利器。

一、 Invisible Indexes:索引界的“隐身侠”

1. 什么是 Invisible Indexes?

顾名思义,Invisible Indexes 就是“不可见”的索引。 啥意思呢? 就是说,这个索引虽然存在于数据库中,但是优化器默认情况下不会使用它。

这个特性非常有用,主要体现在以下几个方面:

  • 安全删除索引: 在删除索引之前,先将其设置为 Invisible,观察一段时间,如果系统运行正常,证明这个索引确实没啥用,就可以放心地删除了。
  • 测试新索引: 在生产环境创建新索引后,先将其设置为 Invisible,然后通过 optimizer_switch 参数手动开启使用,观察性能是否提升,再决定是否正式启用。
  • 控制索引的使用: 在某些情况下,我们可能希望强制优化器不使用某个索引,就可以将其设置为 Invisible。

2. 如何创建和修改 Invisible Indexes?

创建 Invisible Indexes 非常简单,只需要在 CREATE INDEX 语句中加上 INVISIBLE 关键字即可:

CREATE INDEX idx_name ON table_name (column_name) INVISIBLE;

如果要修改一个已有的索引为 Invisible,可以使用 ALTER TABLE 语句:

ALTER TABLE table_name ALTER INDEX idx_name INVISIBLE;

同样,将 Invisible 索引设置为可见,也是用 ALTER TABLE 语句:

ALTER TABLE table_name ALTER INDEX idx_name VISIBLE;

3. 如何让优化器使用 Invisible Indexes?

默认情况下,优化器不会使用 Invisible Indexes。 如果想让优化器使用它,需要修改 optimizer_switch 系统变量。

-- 全局生效
SET GLOBAL optimizer_switch='use_invisible_indexes=on';

-- 会话级别生效
SET SESSION optimizer_switch='use_invisible_indexes=on';

开启之后,优化器在选择执行计划时,就会考虑 Invisible Indexes 了。

4. 举个栗子

假设我们有一张 users 表,结构如下:

CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL,
    age INT,
    city VARCHAR(255)
);

-- 插入一些测试数据
INSERT INTO users (name, email, age, city) VALUES
('张三', '[email protected]', 25, '北京'),
('李四', '[email protected]', 30, '上海'),
('王五', '[email protected]', 28, '广州'),
('赵六', '[email protected]', 35, '深圳');

现在,我们想删除 city 列上的索引,但是又不敢直接删,怎么办?

  1. 创建 Invisible 索引

首先,创建 city 列上的索引,并将其设置为 Invisible:

CREATE INDEX idx_city ON users (city) INVISIBLE;
  1. 观察一段时间

观察一段时间,比如一周或者一个月,看看系统运行是否正常。 如果没有出现任何问题,说明这个索引确实没啥用。

  1. 删除索引
ALTER TABLE users DROP INDEX idx_city;

如果在这期间,发现系统性能下降,说明这个索引还是有用的,可以将其设置为 Visible:

ALTER TABLE users ALTER INDEX idx_city VISIBLE;

5. 注意事项

  • PRIMARY KEY 必须是 Visible 的,不能设置为 Invisible。
  • UNIQUE 索引如果设置为 Invisible,可能会导致数据插入失败。 因为 UNIQUE 索引的主要作用是保证数据的唯一性,如果设置为 Invisible,可能会导致插入重复数据。
  • 查看索引是否可见,可以通过 SHOW INDEXES 命令,或者查询 information_schema.statistics 表。

二、 Online DDL:让 DDL 操作不再“锁表”

1. 什么是 Online DDL?

Online DDL,顾名思义,就是在执行 DDL 操作(比如添加/删除索引、修改列类型等)时,尽量减少对业务的影响,避免长时间的锁表。

在 MySQL 5.6 之前,执行 DDL 操作通常需要锁表,这会导致业务中断。 从 MySQL 5.6 开始,引入了 Online DDL,可以在执行 DDL 操作的同时,允许读写操作,大大提高了数据库的可用性。

2. Online DDL 的实现原理

Online DDL 的实现原理主要依赖于以下两种算法:

  • INPLACE 算法: 在原表上直接进行修改,不需要创建临时表。 这种算法速度快,但是限制较多,比如不能修改列的类型。
  • COPY 算法: 创建一个临时表,将原表的数据复制到临时表中,然后在临时表上进行修改,最后将临时表替换为原表。 这种算法速度慢,但是限制较少,可以修改列的类型。

MySQL 在执行 DDL 操作时,会根据具体的操作和参数,自动选择合适的算法。

3. Online DDL 的语法

在执行 DDL 操作时,可以通过 ALGORITHMLOCK 参数来控制 Online DDL 的行为。

  • ALGORITHM: 指定 DDL 操作使用的算法。 可以取以下值:
    • DEFAULT: 默认算法,由 MySQL 自动选择。
    • INPLACE: 使用 INPLACE 算法。
    • COPY: 使用 COPY 算法。
  • LOCK: 指定 DDL 操作使用的锁级别。 可以取以下值:
    • DEFAULT: 默认锁级别,由 MySQL 自动选择。
    • NONE: 允许并发的读写操作。
    • SHARED: 允许并发的读操作,禁止写操作。
    • EXCLUSIVE: 排他锁,禁止并发的读写操作。

例如,要使用 INPLACE 算法创建一个索引,可以使用以下语句:

ALTER TABLE table_name ADD INDEX idx_name (column_name), ALGORITHM=INPLACE, LOCK=NONE;

4. Online DDL 的限制

虽然 Online DDL 可以减少对业务的影响,但是它也有一些限制:

  • 并非所有的 DDL 操作都支持 Online DDL。
  • Online DDL 操作仍然会占用一定的资源,可能会影响数据库的性能。
  • 在执行 Online DDL 操作期间,可能会出现短暂的锁表。

5. 举个栗子

假设我们需要在 users 表的 email 列上添加一个索引,但是又不想影响业务,怎么办?

ALTER TABLE users ADD INDEX idx_email (email), ALGORITHM=INPLACE, LOCK=NONE;

这条语句会使用 INPLACE 算法创建一个索引,并且允许并发的读写操作。 这样就可以在不影响业务的情况下,完成索引的创建。

6. 注意事项

  • 在执行 Online DDL 操作之前,最好先进行测试,评估其对数据库性能的影响。
  • 在执行 Online DDL 操作期间,要密切关注数据库的运行状态,及时发现和解决问题。
  • 不同的 MySQL 版本对 Online DDL 的支持程度可能不同,要注意查看官方文档。

三、 Invisible Indexes 与 Online DDL 的协同工作

Invisible Indexes 和 Online DDL 可以协同工作,共同解决索引管理的问题。

例如,我们可以先使用 Online DDL 创建一个 Invisible 索引,然后在生产环境观察一段时间,如果性能提升明显,就可以将其设置为 Visible。

-- 使用 Online DDL 创建一个 Invisible 索引
ALTER TABLE users ADD INDEX idx_email (email) INVISIBLE, ALGORITHM=INPLACE, LOCK=NONE;

-- 观察一段时间,如果性能提升明显,就将其设置为 Visible
ALTER TABLE users ALTER INDEX idx_email VISIBLE;

这样可以最大限度地降低风险,保证数据库的稳定性和可用性。

四、 总结

今天我们学习了 Invisible Indexes 和 Online DDL 的基本概念、使用方法和注意事项。 希望大家能够灵活运用这两个特性,更好地管理 MySQL 数据库的索引,提高数据库的性能和可用性。

特性 作用 优点 缺点 使用场景
Invisible Indexes 允许创建对优化器不可见的索引,主要用于安全删除索引、测试新索引和控制索引的使用。 1. 安全删除索引:在删除索引之前,先将其设置为 Invisible,观察一段时间,如果系统运行正常,证明这个索引确实没啥用,就可以放心地删除了。 2. 测试新索引:在生产环境创建新索引后,先将其设置为 Invisible,然后通过 optimizer_switch 参数手动开启使用,观察性能是否提升,再决定是否正式启用。 3. 控制索引的使用:在某些情况下,我们可能希望强制优化器不使用某个索引,就可以将其设置为 Invisible。 1. PRIMARY KEY 必须是 Visible 的,不能设置为 Invisible。 2. UNIQUE 索引如果设置为 Invisible,可能会导致数据插入失败。 因为 UNIQUE 索引的主要作用是保证数据的唯一性,如果设置为 Invisible,可能会导致插入重复数据。 3. 查看索引是否可见,可以通过 SHOW INDEXES 命令,或者查询 information_schema.statistics 表。 1. 评估现有索引的有效性,安全删除无用索引。 2. 在生产环境中测试新索引,评估其性能影响。 3. 临时禁用某些索引,用于问题排查或性能调优。
Online DDL 允许在执行 DDL 操作(比如添加/删除索引、修改列类型等)时,尽量减少对业务的影响,避免长时间的锁表。 1. 减少锁表时间,提高数据库的可用性。 2. 可以在业务高峰期执行 DDL 操作,无需等到业务低谷期。 1. 并非所有的 DDL 操作都支持 Online DDL。 2. Online DDL 操作仍然会占用一定的资源,可能会影响数据库的性能。 3. 在执行 Online DDL 操作期间,可能会出现短暂的锁表。 1. 在生产环境中创建、修改或删除索引,尽量避免对业务造成影响。 2. 修改表结构,例如添加、删除或修改列,尽量减少锁表时间。 3. 执行 ALTER TABLE 操作时,尽量选择 INPLACE 算法,减少资源消耗。

好了,今天的讲座就到这里,感谢大家的观看! 如果大家有什么问题,欢迎随时提问。

发表回复

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