使用时间戳和主键进行表分区

时间:2017-07-13 23:26:10

标签: mysql database-partitioning

我正在将结构化日志数据导入MySQL。我对使用术语“大数据”犹豫不决,但是大小非常重要 - 表中大约有50列,需要每秒连续导入1,000条记录。还要求将所有这些数据导入同一数据库中的同一个表。实际上,我认为任何性能(和理智)的唯一选择是对表结构进行分区。因为它是日志数据,所以有一个时间戳列,我可以放心地假设报告将包含在其查询中,并且是索引和在分区定义中使用的主要候选者。

Murphy’s Law被击中之前,我对这样的事情表示祝你好运:

stripe.js

我一次接收大约100-200行的传入数据,我使用事务和多行INSERT语句推送到数据库。但是,由于数据的输入方式,批次之间可能存在重复记录。举个例子,从10:30:00到10:35:59给出一批,从10:35:00到10:40:59给出下一批,10:35:00到10:35:59之间的记录出现在两个批次中。换句话说,timestamp列是可索引的,但不是主键。

幸运的是,我可以使用的数据中有一个主键。我的目的是执行INSERT IGNORE并让MySQL自己拒绝重复项。我知道我需要改变我的定义,以便强制执行主键,并且我也知道密钥需要包含在分区定义中。主键是VARCHAR(36)并采用以下形式: XXXX-< timestamp> - < sequence> 。因此,例如,时间戳为1499942130的三个唯一记录的主键为XXXX-1499942130-1,XXXX-1499942130-2和XXXX-1499942130-3。

我的问题是如何使用时间戳和主键定义分区,以便将数据存储在物理“月度”表中以便快速检索?

1 个答案:

答案 0 :(得分:2)

我让这个工作:

CREATE TABLE `poorly_designed_log_table` (
  `timestamp` int(10) unsigned NOT NULL,
  `pk` varchar(36) NOT NULL,
  PRIMARY KEY (`timestamp`,`pk`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
PARTITION BY RANGE COLUMNS(`timestamp`, pk)
(PARTITION p0001 VALUES LESS THAN (1483257600, MAXVALUE),
 PARTITION p0002 VALUES LESS THAN (1485936000, MAXVALUE),
 PARTITION p0003 VALUES LESS THAN (1488355200, MAXVALUE)
);

我必须将时间戳添加到PRIMARY KEY约束中,否则会出现此错误:

  

ERROR 1503(HY000):PRIMARY KEY必须包含表格分区功能中的所有列

Partitioning Keys, Primary Keys, and Unique Keys上的MySQL手册说:

  

分区表的分区表达式中使用的所有列必须是表可能具有的每个唯一键的一部分。

因此,使PK具有两列似乎是多余的,但这是必要的。