1

我有一个包含所有系统用户的表。随着时间的推移,一些用户帐户最终会在此表中处于休眠状态和未使用状态。

如果我有大量用户,最好按日期(上次登录日期)对表进行分区,然后根据日期查询用户。例如:您登录并且您的 lastlogondate 已更新,这是分区使用的。

问题:这是否意味着所有当前用户都将在第一个分区中说出,因为他们的日期戳是最新的。这是否是将当前活动用户池保留在一个分区中的好方法,并且过时帐户的重置最终将驻留在其他分区中,具体取决于上次活动日期。(注意:如果用户再次登录,他们将再次激活)。

这是加快查询速度的好方法吗?

4

1 回答 1

3

不,我不会使用这种分区方法。

要从 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;
于 2013-01-07T23:28:26.183 回答