当我们必须更改具有数十亿行的表中的列时,如何处理性能?
2 回答
大表中的DML操作确实是一项非常繁琐的工作,需要在执行操作时进行适当的分析和良好的迁移策略。假设在您的MYSQL 数据库中,您有一个包含 6 亿行的巨型表,具有一些模式操作,例如添加唯一键、更改列,甚至再添加一列,这是一个非常繁琐的过程,需要花费数小时来处理和有时会出现服务器超时。为了克服这一点,必须想出一个非常好的迁移计划,我在下面记下其中一个。
1) 假设有一个表 Orig_X,我必须在其中添加一个默认值为 0 的新列 colNew。
2) 创建一个 Dummy 表 Dummy_X,它是 Orig_X 的副本,但有一个新列 colNew。
3) 使用以下设置将数据从 Orig_X 插入到 Dummy_X。
4) 自动提交设置为零,这样在每个插入语句后不提交数据,影响性能。
5) 二进制日志设置为零,这样就不会在这些日志中写入任何数据。
6)插入数据机器人后,功能设置为一个。
SET AUTOCOMMIT = 0;
SET sql_log_bin = 0;
Insert into Dummy_X(col1, col2, col3, colNew)
Select col1, col2, col3, from Orig_X;
SET sql_log_bin = 1;
SET AUTOCOMMIT = 1;
7)现在可以使用新插入的列创建主键,该列现在是主键的一部分。
8) 现在可以创建所有唯一键。9)我们可以通过发出以下命令来检查服务器的状态
SHOW MASTER STATUS
10) 发出 FLUSH LOGS 也很有帮助,因此 MySQL 将清除旧日志。
11)为了提高性能来运行类似类型的查询,例如上面的插入语句,应该有查询缓存变量。
SHOW VARIABLES LIKE 'have_query_cache';
query_cache_type = 1
以上是大表迁移策略的步骤,下面是我想提高数据库/查询性能的步骤。1) 删除表上所有不必要的索引,特别注意 UNIQUE 索引,因为这些索引在禁用更改缓冲时。如果您没有理由使用该约束,请不要使用 UNIQUE 索引,更喜欢常规 INDEX。
2) 如果批量加载新表,请延迟创建除 PRIMARY KEY 之外的任何索引。如果您在加载数据后创建它们,那么 InnoDB 能够应用预排序和批量加载过程,这既更快又通常会产生更紧凑的索引。
3)更多的内存实际上可以帮助性能优化。如果 SHOW ENGINE INNODB STATUS 在 BUFFER POOL AND MEMORY 下显示任何 reads/s 并且可用缓冲区的数量(也在 BUFFER POOL AND MEMORY 下)为零,您可以从更多中受益(假设您在服务器上正确调整了 innodb_buffer_pool_size 的大小。
4) 通常,您的数据库表在每次插入后都会重新索引。这对您的数据库来说是一些繁重的工作,但是当您的查询被包装在事务中时,在处理完整个批量之前,该表不会被重新索引。节省大量工作。
5) 大多数 MySQL 服务器都启用了查询缓存。它是由数据库引擎悄悄处理的提高性能的最有效方法之一。当多次执行同一个查询时,从缓存中取出结果,速度相当快。
6) 使用 EXPLAIN 关键字可以让您深入了解 MySQL 正在执行您的查询。这可以帮助您发现查询或表结构的瓶颈和其他问题。EXPLAIN 查询的结果将显示正在使用哪些索引、如何扫描和排序表等...
7) 如果您的应用程序包含许多 JOIN 查询,则需要确保您连接的列在两个表上都有索引。这会影响 MySQL 内部如何优化连接操作。
8) 在每个表中都有一个 id 列,它是 PRIMARY KEY、AUTO_INCREMENT 和 INT 的风格之一。也最好是 UNSIGNED,因为该值不能为负数。
9) 即使您的用户表具有唯一的用户名字段,也不要将其作为您的主键。VARCHAR 字段作为主键较慢。通过在内部引用所有用户的 ID,您将在代码中拥有更好的结构。
10) 通常,当您从脚本执行查询时,它将等待该查询的执行完成,然后才能继续。您可以通过使用无缓冲查询来更改它。这为生成大型结果集的 SQL 查询节省了大量内存,并且您可以在检索到第一行后立即开始处理结果集,因为您不必等到执行完完整的 SQL 查询。
11) 对于数据库引擎,磁盘可能是最严重的瓶颈。保持更小更紧凑通常有助于提高性能,以减少磁盘传输量。
12) MySQL 中的两个主要存储引擎是 MyISAM 和 InnoDB。每个都有自己的优点和缺点。MyISAM 非常适合读取繁重的应用程序,但是当有大量写入时,它的扩展性不是很好。即使您正在更新一行的一个字段,整个表也会被锁定,并且在该查询完成之前没有其他进程可以读取它。MyISAM 在计算 SELECT COUNT(*) 类型的查询方面非常快。InnoDB 往往是一个更复杂的存储引擎,对于大多数小型应用程序来说可能比 MyISAM 慢。但它支持基于行的锁定,可以更好地扩展。它还支持一些更高级的功能,例如事务。
pt-online-schema-change
是这样的工具。