tin*_*hen 15 mysql hash datetime database-partitioning
我想通过datetime列对mysql表进行分区.有一天分区.创建表脚本是这样的:
CREATE TABLE raw_log_2011_4 (
id bigint(20) NOT NULL AUTO_INCREMENT,
logid char(16) NOT NULL,
tid char(16) NOT NULL,
reporterip char(46) DEFAULT NULL,
ftime datetime DEFAULT NULL,
KEY id (id)
) ENGINE=InnoDB AUTO_INCREMENT=286802795 DEFAULT CHARSET=utf8
PARTITION BY hash (day(ftime)) partitions 31;
Run Code Online (Sandbox Code Playgroud)
但是当我选择某天的数据时,它找不到分区.select语句是这样的:
explain partitions select * from raw_log_2011_4 where day(ftime) = 30;
Run Code Online (Sandbox Code Playgroud)
当我使用另一个语句时,它可以找到分区,但我没有选择某天的数据.
explain partitions select * from raw_log_2011_4 where ftime = '2011-03-30';
Run Code Online (Sandbox Code Playgroud)
有没有人告诉我如何选择某天的数据并利用分区.谢谢!
小智 20
HASH的分区对于datetime列来说是一个非常糟糕的主意,因为它不能使用分区修剪.来自MySQL文档:
修剪只能用于由HASH或KEY分区的表的整数列.例如,表t4上的此查询无法使用修剪,因为dob是DATE列:
SELECT * FROM t4 WHERE dob >= '2001-04-14' AND dob <= '2005-10-15';
Run Code Online (Sandbox Code Playgroud)
但是,如果表将年份值存储在INT列中,则可以修剪具有WHERE year_col> = 2001 AND year_col <= 2005的查询.
因此,您可以将TO_DAYS(DATE())的值存储在额外的INTEGER列中以使用修剪.
另一种选择是使用RANGE分区:
CREATE TABLE raw_log_2011_4 (
id bigint(20) NOT NULL AUTO_INCREMENT,
logid char(16) NOT NULL,
tid char(16) NOT NULL,
reporterip char(46) DEFAULT NULL,
ftime datetime DEFAULT NULL,
KEY id (id)
) ENGINE=InnoDB AUTO_INCREMENT=286802795 DEFAULT CHARSET=utf8
PARTITION BY RANGE( TO_DAYS(ftime) ) (
PARTITION p20110401 VALUES LESS THAN (TO_DAYS('2011-04-02')),
PARTITION p20110402 VALUES LESS THAN (TO_DAYS('2011-04-03')),
PARTITION p20110403 VALUES LESS THAN (TO_DAYS('2011-04-04')),
PARTITION p20110404 VALUES LESS THAN (TO_DAYS('2011-04-05')),
...
PARTITION p20110426 VALUES LESS THAN (TO_DAYS('2011-04-27')),
PARTITION p20110427 VALUES LESS THAN (TO_DAYS('2011-04-28')),
PARTITION p20110428 VALUES LESS THAN (TO_DAYS('2011-04-29')),
PARTITION p20110429 VALUES LESS THAN (TO_DAYS('2011-04-30')),
PARTITION future VALUES LESS THAN MAXVALUE
);
Run Code Online (Sandbox Code Playgroud)
现在,以下查询将仅使用分区p20110403:
SELECT * FROM raw_log_2011_4 WHERE ftime = '2011-04-03';
Run Code Online (Sandbox Code Playgroud)
嗨您正在对表定义所希望的表的定义执行错误的分区:
CREATE TABLE raw_log_2011_4 (
id bigint(20) NOT NULL AUTO_INCREMENT,
logid char(16) NOT NULL,
tid char(16) NOT NULL,
reporterip char(46) DEFAULT NULL,
ftime datetime DEFAULT NULL,
KEY id (id)
) ENGINE=InnoDB AUTO_INCREMENT=286802795 DEFAULT CHARSET=utf8
PARTITION BY hash (TO_DAYS(ftime)) partitions 31;
Run Code Online (Sandbox Code Playgroud)
你的选择命令是:
explain partitions
select * from raw_log_2011_4 where TO_DAYS(ftime) = '2011-03-30';
Run Code Online (Sandbox Code Playgroud)
上面的命令将选择所需的所有日期,就像使用TO_DAYS命令一样
mysql> SELECT TO_DAYS(950501);
-> 728779
mysql> SELECT TO_DAYS('2007-10-07');
-> 733321
Run Code Online (Sandbox Code Playgroud)
为什么要使用TO_DAYS AS MySQL优化器将识别两个基于日期的函数以进行分区修剪:1.TO_DAYS()2.YEAR()
这将解决你的问题..
| 归档时间: |
|
| 查看次数: |
43753 次 |
| 最近记录: |