我可以将Mysql设置为自动分区吗?

时间:2015-07-20 17:48:52

标签: mysql partitioning

我想分区一个非常大的表。随着业务的增长,按日期划分并不是那么好,因为每年分区越来越大。我真正喜欢的是每1000万条记录的分区。

Mysql手册显示了这个简单的例子:

CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT NOT NULL,
store_id INT NOT NULL
)
PARTITION BY RANGE (store_id) (
PARTITION p0 VALUES LESS THAN (6),
PARTITION p1 VALUES LESS THAN (11),
PARTITION p2 VALUES LESS THAN (16),
PARTITION p3 VALUES LESS THAN MAXVALUE
);

但这意味着大于16且小于MAXVALUE的所有内容都会在最后一个分区中抛出。有没有办法在每个时间间隔(在我的情况下,1000万条记录)自动生成新分区,所以我不必继续修改活动数据库?我正在运行Mysql 5.5

谢谢!

编辑:这是我的实际表格

CREATE TABLE `my_table` (
`row_id` int(11) NOT NULL AUTO_INCREMENT,
`filename` varchar(50) DEFAULT NULL,
`timestamp` datetime DEFAULT NULL,
`unit_num` int(3) DEFAULT NULL,
`string` int(3) DEFAULT NULL,
`voltage` float(6,4) DEFAULT NULL,
`impedance` float(6,4) DEFAULT NULL,
`amb` float(6,2) DEFAULT NULL,
`ripple_v` float(8,6) DEFAULT NULL,
 PRIMARY KEY (`row_id`),
 UNIQUE KEY `timestamp` (`timestamp`,`filename`,`string`,`unit_num`),
 KEY `index1` (`filename`),
 KEY `index2` (`timestamp`),
 KEY `index3` (`timestamp`,`filename`,`string`),
 KEY `index4` (`filename`,`unit_num`)
 ) ENGINE=MyISAM AUTO_INCREMENT=690892041 DEFAULT CHARSET=latin1

并且图表的示例查询是......

SELECT DATE_FORMAT(timestamp,'%Y/%m/%d %H:%i:%s') as mytime,voltage,impedance,amb,ripple_v,unit_num 
FROM my_table WHERE timestamp >= DATE_SUB('2015-07-31 00:05:59', INTERVAL 90 DAY) 
AND filename = 'dlrphx10s320upsab3' and unit_num='5' and string='2'ORDER BY timestamp asc;

以下是查询的解释......

mysql> explain SELECT DATE_FORMAT(timestamp,'%Y/%m/%d %H:%i:%s') as mytime,voltage,impedance,amb,ripple_v,unit_num FROM my_table WHERE timestamp >= DATE_SUB('2015-07-31 00:05:59', INTERVAL 90 DAY) AND filename = 'dlrphx10s320upsab3' and unit_num='5' and string='2'ORDER BY timestamp asc;
+----+-------------+------------+------+-------------------------+--------+---------+-------------+-------+----------------------------------------------------+
| id | select_type | table      | type | possible_keys           | key    | key_len | ref         | rows  | Extra                                              |
+----+-------------+------------+------+-------------------------+--------+---------+-------------+-------+----------------------------------------------------+
|  1 | SIMPLE      | unit_tarma | ref  | timestamp,index3,index4 | index4 | 58      | const,const | 13440 | Using index condition; Using where; Using filesort | 
+----+-------------+------------+------+-------------------------+--------+---------+-------------+-------+----------------------------------------------------+

2 个答案:

答案 0 :(得分:0)

首先,我必须问分区给你的好处是什么?是否有一些查询运行得更快?

没有自动分区。

相反,您应该拥有一个每天运行的作业,并计算“最后一个活动”中的行数。分区,看它是否大约10M。如果是这样,请添加另一个分区。

我建议保持"最后"分区(MAXVALUE的分区)为空。这样你就可以REORGANIZE PARTITION将它分成两个空分区,开销基本为零。而且我建议代替ADD PARTITION,因为你可能会滑倒并在最后一个分区中添加一些内容。

目前还不清楚什么会引发10M。每个store_id都有多行吗?每个商店都有新的行吗?如果是这样,那么在store_id上​​进行分区,因为所有分区都会一直在增长。

好的,所以store_id只是参考手册中的一个例子。请提供SHOW CREATE TABLE,以便我们可以谈论具体,而不是挥手。有太多方法可以完成这项任务。

活动是什么?

如果你大部分都打过最近的"分区,然后可以保证不均匀的分布 - 定期添加新分区并组合相邻的一对旧分区。 (我在一个系统中成功完成了这项工作。)

如果你要清洗" old"数据,然后显然您需要使用PARTITION BY RANGE(TO_DAYS(...))并使用DROP PARTITIONREORGANIZE PARTITION

还有很多其他场景。但我只知道分区提供任何性能优势的4种情况。请参阅my blog

答案 1 :(得分:0)

(这个答案针对架构和SELECT。)

由于您预计会有数百万行,因此我首先要指出对架构的一些改进。

  • FLOAT(m,n)通常是错误的'要做的事,因为它导致两个舍入。使用简单的FLOAT(对于像电压这样的指标,似乎'正确')或使用DECIMAL(m,n)FLOAT是4个字节;在给定的情况下,DECIMAL将是3或4个字节。

  • 当你同时拥有INDEX(a)INDEX(a,b)时,前者是不必要的,因为后者可以涵盖这种情况。你有3个不必要的KEY。这会减慢INSERTs

  • INT(3) - 您是说#3; 3位数字"?如果是这样,请考虑TINYINT UNSIGNED(值0..255)为1个字节而不是INT为4个字节。这将节省许多MB的磁盘空间,因此速度快。 (另请参阅SMALLINT等,SIGNEDUNSIGNED。)

  • 如果重复filename,您可能希望"规范化"它。这样可以节省很多MB。

  • 除非您需要NOT NULL,否则请使用NULL

  • AUTO_INCREMENT=690892041意味着你大约有1/3的灾难发生在id,最高可达20亿。你用id做什么了吗?摆脱专栏将避免这个问题;并将UNIQUE KEY更改为PRIMARY KEY。 (如果确实需要id,请进一步讨论。)

  • ENGINE=MyISAM - 转换有一些有利和不利的后果。该表将变为2-3倍。正确的'选择PRIMARY KEY会显着加快 SELECT的速度。 (并且可能会或可能不会减慢其他SELECTs。)

关于SELECT的说明:由于stringunit_num是查询中的常量,因此ORDER BY timestamp asc, string asc, unit_num asc的最后两个字段是不必要的。如果它们与SELECT中不明显的原因相关,那么我的建议可能不完整。

WHERE filename = 'foobar'
  AND unit_num='40'
  AND string='2' 
  AND timestamp >= ...

INDEX(filename, unit_name, string, timestamp)优化处理。除了 timestamp需要最后之外,列的顺序并不重要。重新排列当前的UNIQUE键,可以为您提供最佳索引。 (同时,没有一个索引对这个SELECT非常有用。)使它成为PRIMARY KEY和表InnoDB会使它更快。

分区?没有优势。不是为了表现;不是你提到的任何其他事情。分区的一个常见用途是清除“旧”。如果您打算这样做,请进一步讨论。

在巨大的牌桌中,最好同时查看所有重要的SELECTs,这样我们就不会在摧毁其他人的速度的同时加快速度。 可能甚至可以证明分区有助于这种权衡。