Skip to main content

32.优化数据变更语句

本节介绍如何加快数据更改语句:INSERT、UPDATE 和 DELETE。 传统的 OLTP 应用程序和现代 Web 应用程序通常会执行许多小型数据更改操作,其中并发性至关重要。 数据分析和报告应用程序通常运行同时影响许多行的数据更改操作,其中主要考虑因素是写入大量数据并使索引保持最新的 I/O。 为了插入和更新大量数据(业内称为 ETL,即“提取-转换-加载”),有时会使用其他 SQL 语句或外部命令来模拟 INSERT、UPDATE 和 DELETE 语句的效果。

优化 INSERT 语句

为了优化插入速度,请将许多小操作组合成一个大操作。 理想情况下,建立一个连接,一次发送许多新行的数据,并将所有索引更新和一致性检查延迟到最后。

插入一行所需的时间由以下因素决定,其中数字表示大致比例:

  • 连接:(3)
  • 向服务器发送查询:(2)
  • 解析查询:(2)
  • 插入行:(1 × 行大小)
  • 插入索引:(1 × 索引数量)
  • 结束:(1)

这没有考虑打开表的初始开销,每个并发运行的查询都会执行一次打开表的开销。

假设 B 树索引,表的大小会使索引的插入速度减慢 log N。

可以使用以下方法来加快插入速度:

如果要同时从同一客户端插入多行,请使用具有多个 VALUES 列表的 INSERT 语句一次插入多行。 这比使用单独的单行 INSERT 语句要快得多(在某些情况下快很多倍)。 如果要将数据添加到非空表中,则可以调整bulk_insert_buffer_size 变量以使数据插入速度更快。

从文本文件加载表时,请使用 LOAD DATA。 这通常比使用 INSERT 语句快 20 倍。

利用列具有默认值这一事实。 仅当要插入的值与默认值不同时才显式插入值。 这减少了MySQL必须做的解析并提高了插入速度。

优化 UPDATE 语句

更新语句的优化类似于 SELECT 查询,但具有额外的写入开销。 写入速度取决于更新的数据量和更新的索引数量。 未更改的索引不会更新。

获得快速更新的另一种方法是延迟更新,然后稍后连续进行多次更新。 如果锁定表,一起执行多个更新比一次执行一个更新要快得多。

对于使用动态行格式的 MyISAM 表,将行更新为更长的总长度可能会拆分行。 如果经常这样做,那么偶尔使用 OPTIMIZE TABLE 就非常重要。

优化 DELETE 语句

删除 MyISAM 表中的各个行所需的时间与索引的数量成正比。 要更快地删除行,可以通过增加 key_buffer_size 系统变量来增加键缓存的大小。

要从 MyISAM 表中删除所有行,TRUNCATE TABLE tbl_name 比 DELETE FROM tbl_name 更快。 截断操作不是事务安全的; 在活动事务或活动表锁定过程中尝试进行操作时会发生错误。