【问题标题】:MySQL Partition Pruning PARTITION BY LISTMySQL 分区修剪 PARTITION BY LIST
【发布时间】:2013-04-02 16:05:20
【问题描述】:

我创建了一个 MySQL 表,它按日期列的月份进行分区,如下所示:

CREATE TABLE `my_big_table` (
  `some_id` varchar(60) COLLATE utf8_unicode_ci NOT NULL,
  `some_value` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
  `some_other_value` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
  `time` datetime NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
PARTITION BY LIST(MONTH(time))
(PARTITION p1 VALUES IN (1) ENGINE = MyISAM,
 PARTITION p2 VALUES IN (2) ENGINE = MyISAM,
 PARTITION p3 VALUES IN (3) ENGINE = MyISAM,
 PARTITION p4 VALUES IN (4) ENGINE = MyISAM,
 PARTITION p5 VALUES IN (5) ENGINE = MyISAM,
 PARTITION p6 VALUES IN (6) ENGINE = MyISAM,
 PARTITION p7 VALUES IN (7) ENGINE = MyISAM,
 PARTITION p8 VALUES IN (8) ENGINE = MyISAM,
 PARTITION p9 VALUES IN (9) ENGINE = MyISAM,
 PARTITION p10 VALUES IN (10) ENGINE = MyISAM,
 PARTITION p11 VALUES IN (11) ENGINE = MyISAM,
 PARTITION p12 VALUES IN (12) ENGINE = MyISAM)

现在,当我跑步时

explain partitions select * from my_big_table where month(time) = 2 limit 10;

我得到输出:

id  select_type table       partitions              type    possible_keys   key key_len ref rows        Extra
1   SIMPLE      my_big_table    p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12  ALL NULL        NULL    NULL    NULL    10762868    "Using where"

显然所有分区都在被读取,我想知道为什么。引擎不应该足够聪明地找出匹配值只能在分区 p2 中找到吗?对于基于日期的查询,我得到相同的输出,例如

explain partitions select * from my_big_table where date(time) = '2013-02-01' limit 10;

有什么线索吗?

干杯,亚历克斯

【问题讨论】:

    标签: mysql partitioning pruning


    【解决方案1】:

    除了PARTITION BY RANGE 之外的所有口味都是无用的。当您有多个值时尤其如此(正如您发现的那样)。

    请考虑PARTITION BY RANGE(TO_DAYS(time)) 并使用WHERE time >= '2014-02-01' AND time < '2014-02-01' + INTERVAL 7 MONTH(作为扫描一个月的示例)。 不要使用MONTH(time)。

    More discussion

    【讨论】:

      【解决方案2】:

      好的,经过更多的谷歌搜索和更多的试验和错误:
      问题似乎与我查询的 where 子句中的 month(...) 或 date(...) 语句有关。查询

      explain partitions select * from my_big_table where time = '2013-02-01 00:00:00' limit 10;
      

      仅按预期扫描分区 p2。因此,似乎分区修剪仅在分区列的原始值是 where 子句的一部分时才有效。

      干杯,亚历克斯

      【讨论】:

        【解决方案3】:

        您永远不应该对表值month(time) = 2 使用函数,MySQL 将始终调查此类查询的所有值(即全表扫描)。

        通常您会发现这种与未使用索引相关的“问题”,但分区修剪也是如此。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-11-29
          • 1970-01-01
          • 1970-01-01
          • 2020-11-18
          • 2012-04-17
          • 1970-01-01
          • 2019-09-16
          相关资源
          最近更新 更多