需要帮助在位列上对MySQL表进行分区,并对结果分区进行子分区

时间:2018-12-11 18:15:12

标签: mysql partitioning mysql-5.7 mysql-8.0

我需要一些帮助来弄清楚如何在MySQL数据库中对下表进行分区,以便首先拥有2个分区,其中1个为活动用户(active column = 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确实令人震惊!

1 个答案:

答案 0 :(得分:1)

子分区

MySQL对您进行子分区时可以做什么和不能做什么进行了严格的限制,引用5.7 manual

  

可以对通过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)
       );

请注意,您需要在PK中添加archive_key才能避免

  

错误1503(HY000):主键必须包含表分区功能中的所有列

有关分区的意见

不,它不会晃动。在这个论坛上展示的大多数用例在没有分区的情况下运行都不会比没有分区时更快。在某些情况下,它们的运行速度会变慢。

当然,有很多选择。我看到的唯一实际性能提高的示例是PARTITION BY RANGE,但即使如此,也仅适用于狭窄的用例(清除时间序列,“查找最近”,工作集位于具有“坏”索引,可移植的单个分区中)表空间)。 Details

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

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

在您的示例中,未对

进行分区
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'

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