MySQL RANGE COLUMNS如何分区工作

时间:2014-05-12 14:11:21

标签: mysql partitioning

我准备了一个小测试表来提出这个问题:

CREATE TABLE `part_two_cols` (
  `period_type_id` int(11) unsigned NOT NULL,
  `geolocation_id` tinyint(4) unsigned NOT NULL,
  m1 int default 0, 
  m2 int default 0,
  m3 int default 0,
  PRIMARY KEY (`period_type_id`,`geolocation_id`),
  KEY `fk_data_basic_group_id` (`geolocation_id`),
  KEY `fk_data_basic_period_type_id` (`period_type_id`)
);

我想要一个双列分区键(与主键中的列相同)。这些列中的每一列都是一个枚举,它可以有3个不同的值:1,2,3。因此所有可能的值如下:

INSERT INTO `part_two_cols` (period_type_id, geolocation_id)
VALUES (1,1), (1,2), (1,3), (2,1), (2,2), (2,3), (3,1), (3,2), (3,3);

现在我有9条记录。我想准备这样的分区,每个记录进入单独的分区。我一直在尝试以下方法:

ALTER TABLE `part_two_cols`
PARTITION BY RANGE COLUMNS(period_type_id, geolocation_id) (
    PARTITION p0 VALUES LESS THAN (2, 2),
    PARTITION p1 VALUES LESS THAN (2, 3),
    PARTITION p2 VALUES LESS THAN (2, 4),
    PARTITION p3 VALUES LESS THAN (3, 2),
    PARTITION p4 VALUES LESS THAN (3, 3),
    PARTITION p5 VALUES LESS THAN (3, 4),
    PARTITION p6 VALUES LESS THAN (4, 2),
    PARTITION p7 VALUES LESS THAN (4, 3),
    PARTITION p8 VALUES LESS THAN (4, 4),
    PARTITION p9 VALUES LESS THAN (MAXVALUE, MAXVALUE)
);

我失败了,因为在测试EXPLAIN PARTITIONS时,结果不符合我的预期:

EXPLAIN PARTITIONS SELECT * FROM `part_two_cols` WHERE period_type_id=1|2|3 AND geolocation_id = 1|2|3;

我得到的结果存储在下表中:

 pt | geo | part
----+-----+------
 1  |  1  |  p0
 1  |  2  |  p0
 1  |  3  |  p0
 2  |  1  |  p0
 2  |  2  |  p1
 2  |  3  |  p2
 3  |  1  |  p3
 3  |  2  |  p4
 3  |  3  |  p5

我想知道为什么所有pt = 1记录都属于分区p0 - 即(1,1),(1,2)和(1,3)?我对单列RANGE COLUMNS进行了检查,发现LESS THAN实际上是LESS(并且不小于或等于,这是我的第一个分析想法)。

问题是:在上面的代码中要改变什么来使每个记录落入一个单独的分区。什么是解释。

1 个答案:

答案 0 :(得分:1)

解决方案非常无意义,至少对我而言。事实证明,当MySQL将记录插入分区表时,它不会比较所有列。它比较第一列,如果条件满足,则进行插入。如果不满意,则检查第二列,依此类推。这就是为什么(1,1)和(1,2),(1,3)和(2,1)都归入p0。这是因为(1,1),(1,2)和(1,3)只有12相比,它是满足的,所以它被插入。对于(2,1),22进行比较,尚未满足,因此它检查第二列,1< 2和第二列满足条件。所以第四条记录仍然属于p0。第五条记录(2,2)与2相比2尚未满足。比较第二列,2< 2。尚未满足,但没有剩下的列,所以它根本不满意,所以它不是p0。但对p1感到满意(第二列比较:2< 3

答案 - 如何使每条记录落入单独的分区 - 如下:

ALTER TABLE `part_two_cols`
PARTITION BY RANGE COLUMNS(period_type_id, geolocation_id) (
    PARTITION p0 VALUES LESS THAN (1, 2),
    PARTITION p1 VALUES LESS THAN (1, 3),
    PARTITION p2 VALUES LESS THAN (2, 1),
    PARTITION p3 VALUES LESS THAN (2, 2),
    PARTITION p4 VALUES LESS THAN (2, 3),
    PARTITION p5 VALUES LESS THAN (2, 4),
    PARTITION p6 VALUES LESS THAN (3, 2),
    PARTITION p7 VALUES LESS THAN (3, 3),
    PARTITION p8 VALUES LESS THAN (3, 4),
    PARTITION p9 VALUES LESS THAN (MAXVALUE, MAXVALUE)
);

这在某种程度上是合乎逻辑的,但是棘手的是我希望一次比较所有列。并且MySQL尽可能少地进行比较。