【问题标题】:MYSQL subpartition pruningMYSQL 子分区修剪
【发布时间】:2016-08-23 11:18:16
【问题描述】:

我有一个 MYSQL 表,其中分区为年,子分区为月。

CREATE TABLE ptable (
   id INT NOT NULL AUTO_INCREMENT, 
   name varchar(100),
   purchased DATETIME NOT NULL,
   PRIMARY KEY (id, purchased)
)

PARTITION BY RANGE( YEAR(purchased) )
SUBPARTITION BY HASH( MONTH(purchased) )
SUBPARTITIONS 12 (
   PARTITION p0 VALUES LESS THAN (2011),
   PARTITION p1 VALUES LESS THAN (2012),
   PARTITION p5 VALUES LESS THAN MAXVALUE
);

我对该表的大部分查询都涉及年份或月份。当我尝试按月查询时,它没有正确修剪并扫描给定年份的所有 12 个子分区。

explain partitions

SELECT *
FROM ptable
WHERE purchased BETWEEN '2011-12-01' AND '2011-12-31';

我的问题是,当我知道年份和月份值时,有没有办法告诉 MYSQL 只查询特定的子分区?或者可能有更好的做法。我正在使用 MYSQL 5.1。

【问题讨论】:

  • mysql 会在分区正确时自动执行,如果我是你,我会将日期转换为 int unsigned 并使用 unix 时间戳进行分区

标签: mysql database-partitioning


【解决方案1】:

http://dev.mysql.com/doc/refman/5.1/en/partitioning-pruning.html 说:

当分区表达式使用 YEAR()TO_DAYS() 函数时,也可以对在 DATE 或 DATETIME 列上分区的表应用修剪。

在 MySQL 5.5 中,他们将 TO_SECONDS() 添加到 MySQL 足够智能以用于分区修剪的函数列表中。

所以您应该能够使用子分区修剪:

SUBPARTITION BY HASH( TO_DAYS(purchased)/30 )

您仍然可以使用 12 个子分区,但您会发现每个月的数据不会与子分区精确对齐。但它会尽可能修剪。

另一种方法是您可以在表格中添加另一列,例如purchased_month TINYINT UNSIGNED,并将 MONTH(purchased) 值冗余地存储在该列中。然后将其用作您的子分区键:

SUBPARTITION BY HASH( purchased_month )

【讨论】:

  • 我坚持使用 5.1,所以 5.5 不是一个选项。 MYSQL 5.1 甚至不允许我按照您的建议进行子分区:SUBPARTITION BY HASH(TO_DAYS(purchased)/30)
  • 是的,你是对的,我的错。那么我所建议的就是在其上存储一个 purchase_month 列和子分区。
【解决方案2】:

从 MySQL 5.6.2 开始,SELECT 支持使用带有分区或子分区列表的 PARTITION 关键字进行显式分区选择

对于使用较新 MySQL 的用户,我们可以使用SELECT * FROM kit.t1 PARTITION (partition_name [, partition_name] ...); 从指定的表(子)分区中选择行

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-17
    • 1970-01-01
    • 1970-01-01
    • 2017-06-14
    相关资源
    最近更新 更多