我们有一个表,大小为 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)
)
数据是不可变的(不需要更新操作。只需批量插入(即每日数据加载)和批量删除(即每月数据清理))。
我们的主要用例是按用户搜索,然后键入创建日期。为此,我正在分析两种策略
- 策略1:通过综合索引:
在 dummy_table(user, type, create_date) 上创建索引 user_type_creation_date_idx
- 策略2:通过分区和索引
alter table dummy_table PARTITION BY LIST(类型)
按哈希进行子分区(年(create_date) + 月(create_date)) (
将 pA 值划分为 (0) (
子分区 s0,
子分区 s1,
……)
在 dummy_table(user) 上创建索引 user_idx
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 属性,因为我们拥有单个(没有任何连接)表的优势,也没有更新需要吗?
- 有没有办法通过并行加载多个文件来提高批量插入速度? 从 S3 加载数据正在阻止其他此类命令。我们可以以某种方式并行运行它们吗?
版本: MySQL:5.6
最佳答案
A 计划:包含索引,不分区,并按 user+type+create_date 对传入数据进行预排序。这将是最快的。但它需要空间来预排序 CSV 文件。
B 计划:无索引,无分区,仅加载数据,然后ADD INDEX
。这需要大量的磁盘空间来进行排序。该计划可能与 A 计划一样快。
计划 C:如果您不需要 id
并且 (user+type+create_date) 是唯一的,则删除 id
并执行A 计划。现在这是最好的方法。
问题:
- 分区不会为您的情况提供任何性能优势。
- 按顺序插入行或通过排序构建索引 - 两者都比随机插入行快得多。
- 更多索引:(用户 + A/B/C/D)——这进一步需要将
用户
作为 PK 中的第一个项。每个用户
有多少行? (听起来有几百万?) - 您提到每月删除。这确实需要 PARTITION BY RANGE(TO_DAYS(...)) 以及每月分区。这是因为
DROP PARTITION
比DELETE
快得多。请参阅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 才支持分区。
这将涉及进行一堆单独的加载,每个加载到一个单独的表中。完成后,使用“可传输表空间”将每个表空间作为分区移动到主表中。
关于mysql - Mysql表批量导入数据,不删除索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54919950/