我自己的电脑(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
并没有多大帮助(当有多个物理硬盘可用时,这更有帮助?)。
对于提高分表性能有什么建议吗?
是的,您的两步可能是最快的方法。并行方法甚至更快。 (稍后会详细介绍。)
最好在
PRIMARY KEY
中定义 CREATE TABLE
,但要延迟添加辅助键,直到填充新表之后。
确保每个步骤都有足够的磁盘空间。 -- 可能需要 700GB 用于分割,然后使用较小的量用于添加二级索引。
将
innodb_buffer_pool_size
设置为 RAM 的 70% 左右。
如果
original_table
和新表都具有 PRIMARY KEY(id)
(或至少以 id
开头),则 Insert..Select 应该是表扫描,并且对于 I/O、CPU 和 buffer_pool 非常高效。
会有多少张新桌子?
假设不超过 20% 的表具有
var1
的特定值,var1
上的索引将被忽略;不用担心。 “表扫描”将比使用索引更有效。
通过同时运行所有INSERT..SELECTs
original_table
一次。
(使用命令行工具“mysql”,这样你就可以并行运行。Workbench 似乎对此不太实用。)
也就是说,“计算磁盘点击次数”在您的特定任务中发挥作用。顺序方法将需要铲除大约 (N+1)x600GB 的数据。并行方法仅涉及大约 2x600GB 的 I/O。即 600GB 读取 + N x 600GB / N 写入每个新表。
如果您有二级索引,那么顺序与并行的权衡就会变得复杂。在我强迫我的大脑做出预测之前,请就索引提出建议。