MySQL表分区按月分配

时间:2013-10-14 07:04:24

标签: mysql partition

我有一个存储许多跟踪事件的巨大表格,例如用户点击。

该表已经达到数百万的数量,并且每天都在增长。 当我尝试从大时间帧中获取事件时,查询开始变慢,并且在阅读了相当多的主题后,我明白分区表可能会提高性能。

我想要做的是按月对表进行分区。

我只找到了指导如何每月手动分区的指南,有没有办法告诉MySQL按月分区,它会自动完成?

如果没有,考虑到我的分区列是一个日期时间,手动执行该命令是什么?

5 个答案:

答案 0 :(得分:10)

正如手册所述:http://dev.mysql.com/doc/refman/5.6/en/partitioning-overview.html

通过对月份输出进行散列分区,可以轻松实现这一点。

CREATE TABLE ti (id INT, amount DECIMAL(7,2), tr_date DATE)
    ENGINE=INNODB
    PARTITION BY HASH( MONTH(tr_date) )
    PARTITIONS 6;

请注意,这仅按月而不是按年分区,此示例中只有6个分区(因此有6个monhts)。

用于分区现有表格(手册:https://dev.mysql.com/doc/refman/5.7/en/alter-table-partition-operations.html):

ALTER TABLE ti
    PARTITION BY HASH( MONTH(tr_date) )
    PARTITIONS 6;

可以从整个表格中查询:

SELECT * from ti;

或来自特定分区:

SELECT * from ti PARTITION (HASH(MONTH(some_date)));

答案 1 :(得分:1)

CREATE TABLE `mytable` (
  `post_id` int DEFAULT NULL,
  `viewid` int DEFAULT NULL,
  `user_id` int DEFAULT NULL,
  `post_Date` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
PARTITION BY RANGE (extract(year_month from `post_Date`))
(PARTITION P0 VALUES LESS THAN (202012) ENGINE = InnoDB,
 PARTITION P1 VALUES LESS THAN (202104) ENGINE = InnoDB,
 PARTITION P2 VALUES LESS THAN (202108) ENGINE = InnoDB,
 PARTITION P3 VALUES LESS THAN (202112) ENGINE = InnoDB,
 PARTITION P4 VALUES LESS THAN MAXVALUE ENGINE = InnoDB)

答案 2 :(得分:1)

注意通过哈希进行分区的“懒惰”效果:

正如文档所说:

您还应该记住,每次插入或更新(或可能删除)行时都会计算此表达式;这意味着非常复杂的表达式可能会导致性能问题,尤其是在执行一次影响大量行的操作(例如批量插入)时。

最有效的散列函数是对单个表列进行操作并且其值随列值增加或减少一致的函数,因为这允许对分区范围进行“修剪”。也就是说,表达式与其所基于的列的值变化得越密切,MySQL 就越能有效地使用该表达式进行哈希分区。

例如,其中 date_col 是类型为 DATE 的列,那么表达式 TO_DAYS(date_col) 被称为直接随 date_col 的值变化,因为对于值的每次变化date_col,表达式的值以一致的方式变化。表达式 YEAR(date_col) 相对于 date_col 的方差并不像 TO_DAYS(date_col) 那样直接,因为并非 date_col 中的每一个可能的变化都会在 {{ 1}}。

答案 3 :(得分:-3)

HASHing按月划分为6个分区,意味着每年有两个月降落在同一分区中。那有什么好处?

不要打扰分区,索引表。

假设这是您使用的仅有两个查询:

SELECT * from ti;
SELECT * from ti PARTITION (HASH(MONTH(some_date)));

然后从PRIMARY KEY开始the_date

第一个查询只是读取整个表;分区与未分区之间没有变化。

第二个查询假设您需要一个月,而不是映射到同一分区的所有月份都需要

SELECT * FROM ti  WHERE the_date >= '2019-03-01'
                    AND the_date  < '2019-03-01' + INTERVAL 1 MONTH;

如果还有其他查询,让我们看看。

(对于使用PARTITION BY HASH,我从未发现任何性能上的合理性。)

答案 4 :(得分:-7)

使用TokuDb,其访问时间与表格大小无关。