使用 load infile 在批量加载之前或之后建立索引?

qma*_*777 6 mysql myisam index bulk import

我有一个超过 1B 行和两列被索引的数据库(除了 PK)。在加载 infile 之前在表中预先定义索引还是在加载数据之后更好地索引?

关于数据大小和系统的一些注意事项:

  • 系统是带有 8 核和 32GB 内存的 Linux(目前已达到最大值,除非我转向新的硬件)
  • DB 是 1B 行,原始数据大小为 150GB 数据。
  • 数据库是 MyISAM,加载后主要是只读的。

Cri*_*rta 5

我尝试了具有类似数据负载的不同解决方案 - 超过 1B - 但我发现更好的是:

来自 MySQL 文档

通过一些额外的工作,LOAD DATA INFILE当表有许多索引时,可以使MyISAM 表的运行速度更快。使用以下程序:

  1. 执行FLUSH TABLES语句或mysqladmin flush-tables命令。

  2. 使用myisamchk --keys-used=0 -rq /path/to/db/tbl_name删除所有使用索引的表。

  3. 使用 将数据插入到表中LOAD DATA INFILE。这不会更新任何索引,因此速度非常快。

  4. 重新创建索引myisamchk -rq /path/to/db/tbl_name。这会在将索引树写入磁盘之前在内存中创建索引树,这比在 LOAD DATA INFILE 期间更新索引要快得多,因为它避免了大量的磁盘搜索。生成的索引树也是完美平衡的。

  5. 执行FLUSH TABLES语句或mysqladmin flush-tables命令。

LOAD DATA INFILE如果您插入数据的 MyISAM 表为空,则自动执行上述优化。自动优化和显式使用过程之间的主要区别在于,您可以让 myisamchk 为索引创建分配比您希望服务器在执行 LOAD DATA INFILE 语句时为索引重新创建分配更多的临时内存

为了从 myisamchk 获得更好的性能,您必须调整一些参数,例如:

--key_buffer_size --myisam_sort_buffer_size --read_buffer_size --write_buffer_size
Run Code Online (Sandbox Code Playgroud)

取决于您的硬件架构

笔记

使用LOCALwith 时LOAD DATA,会在服务器的临时目录中创建文件的副本。这不是tmpdir或slave_load_tmpdir的值决定的目录,而是操作系统的临时目录,在MySQL Server中不可配置。

所以,你有这种问题,你的文件是一个 csv,你可以将你的“巨大”文件分成块

$ split -l (numbersofrowsinfile / ((filesize/tmpsize) + 1)) /path/to/your/<file>.csv
Run Code Online (Sandbox Code Playgroud)

然后LOAD DATA LOCAL对每个块文件重复您的(步骤 3)。


Dav*_*ett 5

我将保持这个答案的通用性,因为 Cristian 看起来已经涵盖了大量 MySQL 特定的考虑因素。

对于批量操作的一般建议肯定是随后删除并重建索引。维护每个索引的树结构平衡的工作量相当高,并且根据插入顺序可能会导致显着的索引碎片(即数据文件中页面的位置)和使用的空间量(可能有部分使用的页面比例较高)。

如果表中没有数据,那么一般建议是:

  1. 删除所有索引。请注意,唯一约束也是索引,但我会将它们保留在适当的位置,除非您完全确定传入数据在这方面是有效的。PK 也是索引,但如果 FK 引用它们,您将无法删除它们(并且只有当您知道传入的数据不包含重复项时,您才应该删除它们)。与普遍看法相反,外键并不意味着所有 RDBMS 中都有索引(请参阅http://www.sqlskills.com/blogs/kimberly/when-did-sql-server-stop-putting-indexes-on-foreign-key-columns / )
  2. 进行批量插入。
  3. 由于该表大部分是只读的,因此请使用高填充因子(如果您的 DBMS 允许您对此进行调整)重建主键(在许多 DBMS 中,这将减少碎片和空间浪费)。
  4. 如果您删除了索引和唯一约束,请重新创建它们,并再次使用高填充因子。如果您有聚集索引,请确保在其他索引和约束之前(重新)创建它。

如果表中已有数据,那么这个建议当然需要仔细重新考虑。我记得一条古老的“经验法则”,如果您要添加或更新超过 70% 的表内容,则值得删除并重新创建索引,否则就不需要,但我不知道该规则是否有任何正确的基础进行实验,或者是由一位专家凭空捏造出来并由其他人重复!此外,如果存在现有数据,如果用户主动使用数据库支持的系统,则删除索引和约束将成为问题。

当然,如果时间允许并且您有一台可以在将数据导入生产之前运行测试的机器,您可以在整个过程中运行自己的基准测试。