添加额外的 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
放在最后.
因此,查询执行如下操作:
- "Partition pruning" -- 根据日期,可能会缩小到一个分区。
- 将 PK 直接向下钻取到相关
venue_id
的连续行。
- 基于zone_ids的数据跳房子。 (在某些情况下,这可能是范围扫描而不是跳转。这取决于版本、id 的数量、id 的值,也许还有月相。
- (如果到此为止)然后获取所需的日期。
从巨大的 table 中获取大量行时,最重要的是尽量减少磁盘命中。我刚才描述的可能比其他情况做得更好。在 venue_id 上进行分区仅对那一列有帮助,但对其余列没有帮助。
您好,我目前有一个 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
放在最后.
因此,查询执行如下操作:
- "Partition pruning" -- 根据日期,可能会缩小到一个分区。
- 将 PK 直接向下钻取到相关
venue_id
的连续行。 - 基于zone_ids的数据跳房子。 (在某些情况下,这可能是范围扫描而不是跳转。这取决于版本、id 的数量、id 的值,也许还有月相。
- (如果到此为止)然后获取所需的日期。
从巨大的 table 中获取大量行时,最重要的是尽量减少磁盘命中。我刚才描述的可能比其他情况做得更好。在 venue_id 上进行分区仅对那一列有帮助,但对其余列没有帮助。