我正在使用MySQL 5.5,我在生产中有一个存储客户交易的现有表。该表的简化版本是:
CREATE TABLE transactions (
id INT NOT NULL AUTO_INCREMENT,
description CHAR(100),
posted DATE,
PRIMARY KEY (id)
) ENGINE=MyISAM
我们正在探索在事务日期使用分区的想法,以便使使用日期过滤的报告执行得更快。由于MySQL Partitioning Keys documentation中解释的主键和分区的限制,以下尝试失败。
mysql> CREATE TABLE transactions (
-> id INT NOT NULL AUTO_INCREMENT,
-> description CHAR(100),
-> posted DATE,
-> PRIMARY KEY (id)
-> ) ENGINE=MyISAM
-> PARTITION BY HASH(MONTH(posted)) PARTITIONS 12;
ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function
可能的解决方法如下:
CREATE TABLE transactions (
id INT NOT NULL AUTO_INCREMENT,
description CHAR(100),
posted DATE,
PRIMARY KEY (id, posted)
) ENGINE=MyISAM
PARTITION BY HASH(MONTH(posted)) PARTITIONS 12;
另一种解决方法是:
CREATE TABLE transactions (
id INT NOT NULL AUTO_INCREMENT,
description CHAR(100),
posted DATE,
KEY (id)
) ENGINE=MyISAM
PARTITION BY HASH(MONTH(posted)) PARTITIONS 12;
在这两种解决方法中,数据库不会停止具有相同ID但发布日期不同的多个记录的情况。有没有办法在发布的字段上使用分区并保持原始的唯一约束?
答案 0 :(得分:3)
我一直面临同样的“问题”,我找到的一个解决方法是将我的桌子分成两部分,在你的情况下会产生类似的结果:
CREATE TABLE transactions (
id INT NOT NULL AUTO_INCREMENT,
description CHAR(100),
PRIMARY KEY (id)
) ENGINE=MyISAM;
另一个:
CREATE TABLE transactions_date (
id INT NOT NULL,
posted DATE
) ENGINE=MyISAM
PARTITION BY HASH(MONTH(posted)) PARTITIONS 12;
显而易见的问题是,您必须向应用程序添加一些额外的逻辑,例如在使用SELECT
语句时需要获取两个表以检索所有数据。您可以使用triggers来帮助您完成与INSERT
,UPDATE
和DELETE
相关的任务。
只是一个注释:DATE
或DATETIME
列中使用partition pruning可以从中受益的唯一功能是:{{1 },YEAR()
和TO_DAYS()
(最后一个仅在MySQL 5.5之后可用)。