添加额外的 HASH 分区到已经 HASH 分区 table

Adding Extra HASH partitions to already HASH partitioned table

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

我是否需要从 table 中删除分区,然后在之后添加 1000 个分区,或者有没有办法将额外的 900 个分区添加到已经分区的 table?

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

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

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

您无需删除分区即可重新分区。它会将这些行插入到一个新的 table 中,因此您不妨一步完成。

只需更改 TABLE 并定义新的分区方案:

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% 没有锁定。它需要在其 运行 的开头和结尾短暂地使用独占元数据锁,因为它需要创建触发器,然后重命名 table 并在末尾删除触发器。任何查询,即使是只读的 SELECT,也会阻塞元数据锁。如果您在完成脚本时遇到问题,请确保您 运行 针对您的 table 的任何查询和交易迅速完成(否则您必须终止它们)。

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)都应以使用 = 测试的任何列开头。然后IN,那么最多一个'range'.

为了PK的唯一性要求,我把id放在最后.

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

  1. "Partition pruning" -- 根据日期,可能会缩小到一个分区。
  2. 将 PK 直接向下钻取到相关 venue_id 的连续行。
  3. 基于zone_ids的数据跳房子。 (在某些情况下,这可能是范围扫描而不是跳转。这取决于版本、id 的数量、id 的值,也许还有月相。
  4. (如果到此为止)然后获取所需的日期。

从巨大的 table 中获取大量行时,最重要的是尽量减少磁盘命中。我刚才描述的可能比其他情况做得更好。在 venue_id 上进行分区仅对那一列有帮助,但对其余列没有帮助。