批量导入Mysql表中的数据而无需删除索引

时间:2019-02-28 06:49:54

标签: mysql innodb

我们有一张10 TB,50亿行的表。

create table dummy_table (
  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  type INT, -- ENUM type, only few fixed values
  create_date DATE,
  user VARCHAR(10),
  A VARCHAR(10),
  B VARCHAR(10),
  C VARCHAR(10),
  D VARCHAR(10)
)

数据是不可变的(不需要更新操作。仅批量插入(即每天数据加载)和批量删除(即每月数据清理))。

我们的主要用例是按用户搜索,然后键入,然后输入creation_date。为此,我正在分析两种策略

  1. STRATEGY1 :通过综合索引:

create index user_type_creation_date_idx on dummy_table(user, type, create_date)

  1. STRATEGY2 :通过分区和索引

alter table dummy_table PARTITION BY LIST(type) SUBPARTITION BY HASH(YEAR(create_date) + MONTH(create_date)) ( PARTITION pA VALUES IN (0) ( SUBPARTITION s0, SUBPARTITION s1, .....) create index user_idx on dummy_table(user)

SELECT操作的执行时间几乎相同。我面临的问题是批量插入。我们正在尝试从其中的s3文件中抽取3000万行(4.2 GB)。

没有索引和分区,加载这么多的数据大约需要360秒。但是,使用 STRATEGY2 时,数据加载时间增加到850秒,而使用 STRATEGY1 时,数据加载时间仍从过去的15000秒开始,并且仍在继续。

删除索引不在范围内,因为创建一个索引需要花费7多个小时,而且我们计划再增加四个复合索引

- index on user, A
- index on user, B
- index on user, C
- index on user, D

这是我的问题:

  • 在许多SO帖子中,我都读过“不创建分区”的信息,但似乎分区概念在批量插入方面表现良好。有什么问题吗 我正在使用STRATEGY1吗?
  • 无论如何,有没有办法提高分区,子分区,mysql / innodb属性之类的大容量插入的速度,因为我们具有单个(无任何连接)表的优势,因此永远不会有 UPDATE 需要吗?
  • 是否通过并行加载多个文件来提高批量插入速度? 从S3加载数据正在阻止其他此类命令。我们可以以某种方式并行运行它们吗?

版本: MySQL:5.6

1 个答案:

答案 0 :(得分:1)

计划A:包括索引,不进行分区,并按user + type + create_date对输入的数据进行预排序。这将是最快的。但是需要空间来对CSV文件进行预排序。

计划B:无索引,无分区,仅加载数据,然后ADD INDEX。这需要大量的磁盘空间来进行排序。该计划可能接近计划A。

计划C:如果您不需要id 并且(用户+类型+创建日期)是唯一的,则删除id并执行计划A。现在这是最好的方法。

问题:

  • 分区不会为您的情况带来性能优势。
  • 按顺序插入行或通过排序建立索引-比随机插入行要快得多。
  • 更多索引:(用户+ A / B / C / D)-进一步需要将user作为PK中的 first 项。每个user有多少行? (听起来像几百万?)
  • 您提到了每月删除。这确实需要PARTITION BY RANGE(TO_DAYS(...))以及每月分区。这是因为DROP PARTITIONDELETE快得多。有关更多详细信息,请参见this。因此,现在我建议使用A或C,再加上每月分区。
  • 如果您必须拥有id,那么为了受益于普通SELECT(并且由于数据量巨大),

PRIMARY KEY(user, type, create_date, id), -- clustered, unique, etc
INDEX(id)   -- sufficient to keep AUTO_INCREMENT happy

数学使我感到困惑:5B行(每个行约100个字节)大约为1TB(扣除InnoDB开销之后),但是您说的是10TB。

我假设使用InnoDB;如果您使用的是其他引擎,则可能需要修改答案。

进一步思考“开箱即用” ...

对于InnoDB和并行加载,您应该能够对“可移动表空间”执行以下操作。但是直到5.7.4才可用于分区。

这将涉及一堆单独的加载,每个加载都加载到单独的中。完成后,使用“可移动表空间”将它们作为分区移入主表。