17

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

这张桌子已经有几十万,而且每天都在变大。当我尝试从大的时间范围内获取事件时,查询开始变慢,并且在阅读了相当多的主题后,我了解到对表进行分区可能会提高性能。

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

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

如果不是,考虑到我的按列分区是日期时间,手动执行的命令是什么?

4

5 回答 5

20

如手册所述: 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 个月)。

对于现有表的分区(手册: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)));
于 2013-10-14T07:44:41.920 回答
3
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)
于 2020-11-24T11:57:29.447 回答
1

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

正如文档所说:

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

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

例如,如果 date_col 是 类型的列DATE,则表示表达式TO_DAYS(date_col)直接随 的值变化date_col,因为对于 date_col 的值的每次变化,表达式的值都会以一致的方式变化。表达式YEAR(date_col)相对于的方差date_col并不像 的那样直接TO_DAYS(date_col),因为并非 的每个可能变化都会date_col产生 的等效变化YEAR(date_col)

于 2021-02-04T21:26:31.823 回答
-2

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

不要打扰分区,索引表。

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

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

然后PRIMARY KEYthe_date.

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

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

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

如果您还有其他疑问,让我们看看。

(我还没有找到任何使用 . 的性能理由PARTITION BY HASH。)

于 2020-01-26T03:08:14.457 回答
-15

使用具有独立于表大小的访问时间的 TokuDb。

于 2017-02-20T15:26:31.957 回答