不,我不会使用这种分区方法。
要从 MySQL 分区修剪中受益,您的查询必须引用分区键的列。因此,为了使您提出的分区方案产生任何好处,您对用户的所有查询都需要引用 last_login 列,并且您需要不断更新与 last_login 列进行比较的值:
SELECT ... FROM users WHERE user_name = 'Adam' AND last_login >= '2013-01-01'
-- remember to change this to '2013-02-01' by next month
如果没有搜索特定 last_login 的术语,查询将不得不扫描所有分区。
我也会担心“分区流失”,即行经常从一个分区移动到另一个分区。
还记得在 MySQL 中,分区列必须是表中每个主键或唯一键的一部分。所以使用 last_login 作为分区键需要你定义你的表:
CREATE TABLE Users (
user_name VARCHAR(12) NOT NULL,
last_login DATETIME NOT NULL,
...
PRIMARY KEY (user_name, last_login)
);
这会打开另一个用户创建帐户“Adam”的可能数据异常,只要他们有不同的上次登录时间。两个帐户可以无限期地存在于同一个表中,直到两个亚当碰巧同时登录。然后可能会因为违反主键而被拒绝登录。这将是一个非常令人费解的拒绝登录的原因。
一个稍微好一点的分区方案是这样的:
CREATE TABLE Users (
user_name VARCHAR(12) NOT NULL,
last_login DATETIME NOT NULL,
is_archived TINYINT(1) NOT NULL DEFAULT 0,
...
PRIMARY KEY (user_name, is_archived)
) PARTITION BY HASH(is_archived) PARTITIONS 2;
目的是您定期运行作业以手动归档用户:
UPDATE Users SET is_archived=1 WHERE last_login < CURDATE() - INTERVAL 30 DAY;
这解决了分区流失问题和分区创建杂务问题。它仍然可能允许存在多个“亚当”,但如果您仔细控制将一行从一个分区移动到另一个分区的实例,那么风险应该较低。
您仍然必须在查询中引用分区键,但您比较的值将是固定的:
SELECT ... FROM users WHERE user_name = 'Adam' AND is_archived = 0;