将额外的HASH分区添加到已HASH分区的表中

时间:2019-03-25 11:01:27

标签: mysql partitioning

您好,我目前有一个包含100个HASH分区的表。我决定,由于将来需要扩展,现在需要将其增加到1000个分区。

我是否需要从表中删除分区,然后在其后添加1000个分区,或者是否有办法向已经分区的表中添加额外的900个分区?

我的分区方式是使用下面的代码。

ALTER TABLE t1
PARTITION BY HASH(venue_id)
PARTITIONS 100;

是否还有一种方法可以估算将1000个分区添加到我的表需要多长时间?我将使用perconas工具之一来执行此操作,这将防止表被锁定。 https://www.percona.com/doc/percona-toolkit/LATEST/pt-online-schema-change.html

2 个答案:

答案 0 :(得分:1)

您无需删除分区即可重新分区。无论如何,这些行都将插入到新表中,因此您最好一步就完成。

仅更改表并定义新的分区方案:

ALTER TABLE t1
PARTITION BY HASH(venue_id)
PARTITIONS 1000;

或使用pt-online-schema-change:

pt-online-schema-change h=myhost,D=mydatabase,t=t1 
  --alter "PARTITION BY HASH(venue_id) PARTITIONS 1000" 
  --execute

(为了避免换行,我在其中放置了换行符,但这是一个命令。)


我忘了对您的另一个问题进行评论,有关预测完成的预计到达时间。

Percona脚本的一个优点是它报告进度,您可以据此估算完成情况。尽管在我们的环境中,我们发现它不是很准确。有时它可以报告说它已经完成了99%的工作时间。

还请记住,Percona脚本不是没有锁定的100%。它需要在运行的开始和结束时短暂地使用一个独占元数据锁,因为它需要创建触发器,然后重命名表并在末尾删除触发器。任何查询,甚至是只读的SELECT,都将阻止元数据锁定。如果您在完成脚本时遇到麻烦,请确保对表运行的所有查询和事务都能快速完成(否则,必须杀死它们)。

答案 1 :(得分:0)

PARTITION BY HASH实际上是没有用的。我不希望它对100个分区或1000个分区有帮助。

安排venue_id作为PRIMARY KEY的第一列,您将获得更多收益。

查询是否始终只有一个venue_id? (如果没有,这些选项会变得更混乱。)现在,我假设您一直有WHERE venue_id = constant

您有一个多维索引问题。 INDEXes只是一个维度,所以事情变得棘手。但是,可以使用分区来获得二维索引。

让我们选择day_epoch作为分区键并使用PARTITION BY RANGE(day_epoch)。 (如果将其从4字节的INT更改为3字节的DATE,则使用PARTITION BY RANGE(TO_DAYS(day_epoch))。)

然后让我们决定PRIMARY KEY。注意:添加或删除分区时,应该重新考虑PK。请记住,PK是唯一索引。并且数据聚集在PK上。 (但是,不能保证跨分区的唯一性。)

所以...

PARTITION BY RANGE(day_epoch)

PRIMARY KEY(venue_id, zone_id, id)  -- in this order

我建议不进行分区

PRIMARY KEY(venue_id, zone_id, day_epoch, id)

通常,任何索引(包括PK)都应该以{{1​​}}测试的任何列开头。然后是=,然后是一个“范围”。

为了满足PK的唯一性要求,我将IN last 放在了最后。

因此,查询执行的操作如下:

  1. “分区修剪”-可能会根据日期降到单个分区。
  2. 直接将PK向下钻到有问题的id的连续行中。
  3. 根据zone_ids对数据进行跳查。 (在某些情况下,这可能是一次范围扫描,而不是跳来跳去。这取决于版本,ID的数量,ID的值以及月亮的相位。
  4. (如果可以做到这一点,则可以)获取所需的日期。

从巨大的表中获取许多行时,最重要的是最大程度地减少磁盘命中。我刚才描述的可能比其他情况做得更好。对site_id进行分区仅对那一列有所帮助,而对其余的列则无济于事。