MySQL 中按月存储的 RANGE 与 HASH 分区
RANGE vs HASH partitioning for storage by Month in MySQL
对于我的 Table,我需要根据 created
timestamp 字段按 Month 进行分区。
我正在评估以下两种方法:
范围
ALTER TABLE my_table
PARTITION BY RANGE ( MONTH(created) ) (
PARTITION p1 VALUES LESS THAN (2),
PARTITION p2 VALUES LESS THAN (3),
PARTITION p3 VALUES LESS THAN (4),
PARTITION p4 VALUES LESS THAN (5),
PARTITION p5 VALUES LESS THAN (6),
PARTITION p6 VALUES LESS THAN (7),
PARTITION p7 VALUES LESS THAN (8),
PARTITION p8 VALUES LESS THAN (9),
PARTITION p9 VALUES LESS THAN (10),
PARTITION p10 VALUES LESS THAN (11),
PARTITION p11 VALUES LESS THAN (12),
PARTITION p12 VALUES LESS THAN (13)
);
HASH
ALTER TABLE my_table
PARTITION BY HASH((YEAR(created) * 100) + MONTH(created))
PARTITIONS 13;
用例:
我的用例是我想按月归档,对于跨过 1 年的月份。例如,如果当前月份是 2020 年 7 月,那么对应于 2019 年 7 月的分区将被归档,次要用例是分区修剪以提高性能,因为大多数查询都包含此时间戳列。
为什么HASH一个里有13个分区?
如上所述,我将从本月开始归档第 13 个月。
对于这个用例,哪种方法更适合?据我了解,当我通过 RANGE 定义它时,我可以直接控制哪些数据进入哪个分区,如果是 HASH,它将由 MySQL HASH 函数定义(mod),这将使识别“超过一年”的分区和专门存档变得困难。
或者这个用例是否有任何完全不同的方法?
PARTITION BY HASH
没用。期间.
如果您想清除“旧”数据,PARTITION BY RANGE
会很有用。详情:http://mysql.rjweb.org/doc.php/partitionmaint
明年一月你会做什么?
告诉我你的 SELECTs
和 SHOW CREATE TABLE
。我将帮助您优化非分区版本的 INDEXes
。它将 运行 与您认为的架构一样快或更快。
更多
当你有一个“范围”时,BY HASH
是没有用的。优化器将始终选择所有分区,从而减慢查询速度。 (此缺陷适用于大多数分区方法。)
- 如果您总是使用
WHERE month=constant
,您还不如在索引的前面有列 month
。 MONTH(date_col) = constant
是另一回事。 (我还没有想清楚所有的含义。让我们看看你的问题。)
- 作为一般规则,您可以在非分区 table 上构建索引,该索引将提供与分区 p运行ing 等效的功能。 (link 仅列出了规则的 4 个例外。我花了十年时间寻找更多用例。)相关性: 切换 to/from 分区时,所有应该重新设计索引,包括
PRIMARY KEY
。
- 我的一个用例是使用“transportable tablespaces”来归档整个分区。您 可能 可以将其与
BY HASH
一起使用;很清楚如何使用 BY RANGE
.
- 我博客的主要重点是解释
DROPping
(或 'transporting')最旧的 13 个月分区和 REORGANIZE
以获得新的“月份”(或其他时间范围)。
对于我的 Table,我需要根据 created
timestamp 字段按 Month 进行分区。
我正在评估以下两种方法:
范围
ALTER TABLE my_table PARTITION BY RANGE ( MONTH(created) ) ( PARTITION p1 VALUES LESS THAN (2), PARTITION p2 VALUES LESS THAN (3), PARTITION p3 VALUES LESS THAN (4), PARTITION p4 VALUES LESS THAN (5), PARTITION p5 VALUES LESS THAN (6), PARTITION p6 VALUES LESS THAN (7), PARTITION p7 VALUES LESS THAN (8), PARTITION p8 VALUES LESS THAN (9), PARTITION p9 VALUES LESS THAN (10), PARTITION p10 VALUES LESS THAN (11), PARTITION p11 VALUES LESS THAN (12), PARTITION p12 VALUES LESS THAN (13) );
HASH
ALTER TABLE my_table PARTITION BY HASH((YEAR(created) * 100) + MONTH(created)) PARTITIONS 13;
用例:
我的用例是我想按月归档,对于跨过 1 年的月份。例如,如果当前月份是 2020 年 7 月,那么对应于 2019 年 7 月的分区将被归档,次要用例是分区修剪以提高性能,因为大多数查询都包含此时间戳列。
为什么HASH一个里有13个分区?
如上所述,我将从本月开始归档第 13 个月。
对于这个用例,哪种方法更适合?据我了解,当我通过 RANGE 定义它时,我可以直接控制哪些数据进入哪个分区,如果是 HASH,它将由 MySQL HASH 函数定义(mod),这将使识别“超过一年”的分区和专门存档变得困难。
或者这个用例是否有任何完全不同的方法?
PARTITION BY HASH
没用。期间.
如果您想清除“旧”数据,PARTITION BY RANGE
会很有用。详情:http://mysql.rjweb.org/doc.php/partitionmaint
明年一月你会做什么?
告诉我你的 SELECTs
和 SHOW CREATE TABLE
。我将帮助您优化非分区版本的 INDEXes
。它将 运行 与您认为的架构一样快或更快。
更多
-
当你有一个“范围”时,
BY HASH
是没有用的。优化器将始终选择所有分区,从而减慢查询速度。 (此缺陷适用于大多数分区方法。)- 如果您总是使用
WHERE month=constant
,您还不如在索引的前面有列month
。MONTH(date_col) = constant
是另一回事。 (我还没有想清楚所有的含义。让我们看看你的问题。) - 作为一般规则,您可以在非分区 table 上构建索引,该索引将提供与分区 p运行ing 等效的功能。 (link 仅列出了规则的 4 个例外。我花了十年时间寻找更多用例。)相关性: 切换 to/from 分区时,所有应该重新设计索引,包括
PRIMARY KEY
。 - 我的一个用例是使用“transportable tablespaces”来归档整个分区。您 可能 可以将其与
BY HASH
一起使用;很清楚如何使用BY RANGE
. - 我博客的主要重点是解释
DROPping
(或 'transporting')最旧的 13 个月分区和REORGANIZE
以获得新的“月份”(或其他时间范围)。