0

我需要一些帮助来弄清楚如何在 MySQL 数据库中对下表进行分区,以便我首先有 2 个分区,1 个活动用户(active列 = true)和另一个非活动用户。然后我想按年对非活动用户分区进行子分区(在archive_key以 YEAR(4) 作为数据类型的列上)。我想我知道如何做到这一点,但我不敢尝试以防我没有正确执行它。

谁能帮我实现这一目标?我目前正在使用 MySQL 5.7 和 8 版本。感谢可以提供的任何建议。

CREATE TABLE users_table (
  row_id int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  first_name varchar(255) DEFAULT NULL,
  last_name varchar(255) DEFAULT NULL,
  ...
  createdby varchar(255) DEFAULT NULL,
  createdat datetime DEFAULT NULL,
  lastmodby varchar(255) DEFAULT NULL,
  lastmodat datetime DEFAULT NULL,
  active bit(1) NOT NULL DEFAULT b'0',
  archive_key year(4) GENERATED ALWAYS AS (YEAR(createdat)) STORED,
  PRIMARY KEY (row_id, active),
)
ENGINE = INNODB,
AUTO_INCREMENT = 84771,
AVG_ROW_LENGTH = 166,
CHARACTER SET utf8,
COLLATE utf8_unicode_ci;

顺便说一句,喜欢分区给你的灵活性!MySQL 真的很震撼!

4

1 回答 1

1

子分区

MySQL 对子分区时可以做什么和不能做什么有很大的限制,引用5.7 手册

可以对按 RANGE 或 LIST 分区的表进行子分区。子分区可以使用 HASH 或 KEY 分区

这意味着您正在查看以下内容:

CREATE TABLE users_table (
  row_id int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  first_name varchar(255) DEFAULT NULL,
  last_name varchar(255) DEFAULT NULL,
  createdby varchar(255) DEFAULT NULL,
  createdat datetime DEFAULT NULL,
  lastmodby varchar(255) DEFAULT NULL,
  lastmodat datetime DEFAULT NULL,
  active bit(1) NOT NULL DEFAULT b'0',
  archive_key year(4),
  PRIMARY KEY (row_id, active, archive_key)
)
       ENGINE = INNODB,
       CHARACTER SET utf8,
       COLLATE utf8_unicode_ci
       PARTITION BY LIST(active)
           SUBPARTITION BY HASH(`archive_key`)
           SUBPARTITIONS 4
       (
            PARTITION inactive VALUES IN (0),
            PARTITION active   VALUES IN (1)
       );

注意需要archive_key在PK中包含以避免

ERROR 1503 (HY000): PRIMARY KEY 必须包含表的分区函数中的所有列

关于分区的意见

不,它不摇滚。这个论坛上介绍的大多数用例在使用分区时运行速度并不比不使用时快。在某些情况下,它们运行速度较慢。

当然,有很多选择。我看到的唯一实际性能改进是PARTITION BY RANGE,但即使这样也仅适用于狭窄的用例(清除时间序列、“查找最近”、工作集位于具有“坏”索引、可传输表空间的单个分区中)。 细节

“分区修剪”加速查询是一个神话。具有合适索引的非分区表可能至少会以同样快的速度运行。

注意:要利用添加(或删除)分区,您必须重新评估索引。

在您的示例中,非分区与

INDEX(active, createdat)   -- in this order

WHERE active = 1
  AND createdat >= '2017/01/01'
  AND createdat  < '2017/01/01' + INTERVAL 1 YEAR

或者

INDEX(active, active_key)   -- in this order

WHERE active = 1
  AND archive_key = '2017'

(前者不需要生成的列。)

于 2018-12-13T18:23:33.047 回答