【问题标题】:Need help partitioning a MySQL table on a bit column with subpartitioning on resulting partitions需要帮助在位列上对 MySQL 表进行分区,并在结果分区上进行子分区
【发布时间】:2018-12-11 18:15:12
【问题描述】:

我需要一些帮助来弄清楚如何在 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 真的很棒!

【问题讨论】:

    标签: mysql partitioning mysql-5.7 mysql-8.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以避免

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

    关于分区的意见

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

    当然,有很多选择。我看到实际性能改进的唯一一个是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'
    

    (前者不需要生成列。)

    【讨论】:

    • 感谢您回答我的问题,但尊重我并没有要求对我的分区用例提出批评或意见...我已经评估了这样做的利弊/成本效益并在考虑所有因素后选择在此表上实施。现在,如果您愿意就如何继续我的要求提供一些帮助,我很乐意听到。不过还是谢谢你! (这个回答绝不是刻薄...我只是不想让你的回答劝阻其他人回答我的问题。)
    • @tfrancois - 我添加了一个至少有正确语法的CREATE TABLE
    • 感谢您更新的答案...这正是我想要的。祝您和您的家人节日快乐。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多