根据列的值快速拆分 MySQL 表
Posted
技术标签:
【中文标题】根据列的值快速拆分 MySQL 表【英文标题】:Fast splitting a MySQL table based on the values of a column 【发布时间】:2022-01-05 23:47:55 【问题描述】:我在自己的计算机 (Win10) 上有一个相当大的 mysql 表 (~600G),结构如下。
id var1 var2 var3
a val1 1 5
b val1 2 6
c var2 3 7
d var2 4 8
id
和 var1
都已编入索引。我想根据 var1 的值将该表拆分为几个子表。也就是说,
表table_var1
:
id var1 var2 var3
a val1 1 5
b val1 2 6
对于表'table_var2':
id var1 var2 var3
c val2 3 7
d val2 4 8
我使用了以下代码
CREATE TABLE table_var1 LIKE original_table;
INSERT INTO table_var1 SELECT * FROM original_table where var1=val1;
CREATE TABLE table_var2 LIKE original_table;
INSERT INTO table_var2 SELECT * FROM original_table where var1=val2;
我的问题与this 非常相似。我想加快拆分表的速度,但是由于数据库在我自己的计算机上,如果我没记错的话,partition
并没有真正的帮助(当有多个物理硬盘可用时,这更有帮助?)。
有没有提高分表性能的建议?
【问题讨论】:
为什么要拆分表?我想不出这样做的充分理由 您遇到的实际问题是什么? @ysth 我需要加快拆分速度。我需要对某些列进行进一步处理(例如,基于 var2 或 var3 为表创建更多列),但是,对于不同的 var1 值,操作会有所不同,因此,我想将此表拆分为子表和对子表分别执行这些操作。 不,您希望通过拆分解决什么问题?一般来说,子表是一个糟糕的主意,会让很多事情变得更麻烦 什么版本的 MySQL? 【参考方案1】:是的,您的两个步骤可能是最快的方法。更快的是并行方法。 (稍后会详细介绍。)
最好在CREATE TABLE
中定义PRIMARY KEY
,但延迟添加辅助键,直到填充新表之后。
确保每个步骤都有足够的磁盘空间。 -- 可能 700GB 用于拆分,然后少量用于添加二级索引。
将innodb_buffer_pool_size
设置为大约 70% 的 RAM。
如果original_table
和新表都有PRIMARY KEY(id)
(或至少以id
开头),则Insert..Select 应该是表扫描并且对于I/O、CPU 和buffer_pool 非常有效。
会有多少新表?
假设不超过 20% 的表有 var1
的特定值,var1
上的索引将被忽略;别担心。 “表扫描”将比使用索引更有效。
可能可以通过运行所有INSERT..SELECTs
同时(来自不同的连接)来进一步加快进程。假设 buffer_pool 小于 600GB 的表大小,顺序扫描将涉及该表的多次完全加载——大量 I/O。并行扫描将(可能)导致只获取一次original_table
。
(使用命令行工具“mysql”,以便您可以并行运行。Workbench 似乎对此不实用。)
也就是说,“计算磁盘命中次数”会在您的特定任务中发挥作用。顺序方法将需要大约 (N+1)x600GB 的数据被铲除。并行方法只涉及大约 2x600GB 的 I/O。即 600GB 读取 + N x 600GB / N 写入每个新表。
如果您有二级索引,这会使顺序与并行的权衡变得复杂。在我给大脑施加压力以做出预测之前,请提供有关索引的建议。
【讨论】:
以上是关于根据列的值快速拆分 MySQL 表的主要内容,如果未能解决你的问题,请参考以下文章