使用MySQL中基本SELECT语句的所有分区的分区表

时间:2015-10-20 20:29:25

标签: mysql sql partitioning

我在year(date)的函数中有一个由HASH划分的MySQL表。目标是将我的数据或多或少地分配到每年的分区中。

执行基本选择语句时:

EXPLAIN PARTITIONS
SELECT date 
FROM date_table 
WHERE date >= '2008-01-01' AND date <= '2009-01-01'

...正在使用所有分区。我假设只使用了一些分区,最大值为2.我在这里关于分区如何工作我缺少什么?

TEST.SQL

DROP TABLE IF EXISTS `tmp_date_table`;

CREATE TABLE `tmp_date_table` (
    `date_id` INT(11) NOT NULL,
    `date` DATE NOT NULL,
    PRIMARY KEY (`date_id`, `date`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
PARTITION BY HASH (year(date))
PARTITIONS 11 
;

INSERT INTO `tmp_date_table`(date_id, date) 
VALUES
(1, '2000-01-01'),
(2, '2001-01-01'),
(3, '2002-01-01'),
(4, '2003-01-01'),
(5, '2004-01-01'),
(6, '2005-01-01'),
(7, '2006-01-01'),
(8, '2007-01-01'),
(9, '2008-01-01'),
(10, '2009-01-01'),
(11, '2010-01-01');

EXPLAIN PARTITIONS
SELECT date FROM tmp_date_table WHERE date >= '2008-01-01' AND date <= '2009-01-01';

DROP TABLE IF EXISTS `tmp_date_table`;

感谢任何帮助。

2 个答案:

答案 0 :(得分:3)

所以看起来你的设置正确,我挖了一点。

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

  

当表由HASH或[LINEAR] KEY分区时,修剪只能用于整数列。例如,此语句不能使用修剪,因为dob是DATE列:

SELECT * FROM t4 WHERE dob >= '2001-04-14' AND dob <= '2005-10-15';

所以你不能用HASH做你正在做的事。

  

但是,如果表将年份值存储在INT列中,则a   具有WHERE year_col&gt; = 2001 AND year_col&lt; = 2005的查询可以   修剪。

这对我来说似乎有点直观,但部分原因是您必须始终必须指定分区数量预先(在您的情况下为11),因此分区计算正是如此:

  

如果您将记录插入到col3值为“2005-09-15”的t1中,那么   存储它的分区确定如下:

MOD(YEAR('2010-09-01'),11)
=  MOD(2010,11)
=  8

因此,这将进入分区8而不是分区11,这意味着:

MOD(YEAR('2000-09-01'),11)
=  MOD(2000,11)
=  9

您的第一年将进入分区9.如果您仅在日期查询,它将使用正确的分区:

WHERE date = "2010-01-01"

但不在范围内。

由于您的数据范围是已知的,并且它看起来都是历史性的,因此您必须咬紧牙关并为每年设置一个范围。但是,这样,当您使用BETWEEN时,范围查询将仅使用正确的分区。

DROP TABLE IF EXISTS `tmp_date_table`;

CREATE TABLE `tmp_date_table` (
    `date_id` INT(11) NOT NULL,
    `dates` DATE NOT NULL
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
PARTITION BY RANGE ( YEAR(`dates`) ) (
    PARTITION p0 VALUES LESS THAN (2001),
    PARTITION p1 VALUES LESS THAN (2002),
    PARTITION p2 VALUES LESS THAN (2003),
    PARTITION p3 VALUES LESS THAN (2004),
    PARTITION p4 VALUES LESS THAN (2005),
    PARTITION p5 VALUES LESS THAN (2006),
    PARTITION p6 VALUES LESS THAN (2007),
    PARTITION p7 VALUES LESS THAN (2009),
    PARTITION p8 VALUES LESS THAN (2010),
    PARTITION p9 VALUES LESS THAN (2011),
    PARTITION p10 VALUES LESS THAN MAXVALUE

);

INSERT INTO `tmp_date_table`(date_id, `dates`) 
VALUES
(1, '2000-01-01'),
(2, '2001-01-01'),
(3, '2002-01-01'),
(4, '2003-01-01'),
(5, '2004-01-01'),
(6, '2005-01-01'),
(7, '2006-01-01'),
(8, '2007-01-01'),
(9, '2008-01-01'),
(10, '2009-01-01'),
(11, '2010-01-01'),
(12, '2012-01-01');



EXPLAIN PARTITIONS
SELECT dates FROM tmp_date_table WHERE (`dates`) BETWEEN  "2001-01-01" and "2004-01-01" ;

DROP TABLE IF EXISTS `tmp_date_table`;

答案 1 :(得分:0)

您已找到PARTITION BY HASH几乎无用的主要原因。

但是,更基本......为什么这样做?

CREATE TABLE `tmp_date_table` (
    `date_id` INT(11) NOT NULL,
    `date` DATE NOT NULL,
    PRIMARY KEY (`date_id`, `date`)
)

你是否试图将日期'标准化'到date_id?

  1. date_idINT,占用4个字节。 DATE仅占用3个字节。所以这种规范化浪费了空间。

  2. 不要规范化“连续”事物,例如数字,日期,浮点数等。它会阻止您有效地查找此类值的“范围”。