简体   繁体   English

MYSQL:分区表保持id唯一

[英]MYSQL: Partitioning Table keeping id unique

We are using a table which has schema like following:- 我们使用的表格如下:

CREATE TABLE `user_subscription` (
`ID` varchar(40) NOT NULL,
`COL1` varchar(40) NOT NULL,
`COL2` varchar(30) NOT NULL,
`COL3` datetime NOT NULL,
`COL4` datetime NOT NULL,
`ARCHIVE` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`)
)

Now we wanted to do partition on column ARCHIVE. 现在我们想在列ARCHIVE上进行分区。 ARCHIVE can have only 2 values 0 or 1 and so 2 partitions. ARCHIVE只能有2个值0或1,因此有2个分区。

Actually in our case, we are using partitioning as a Archival process. 实际上在我们的例子中,我们使用分区作为存档过程。 To do partition, we need to make ARCHIVE column as a part of primary key. 要进行分区,我们需要将ARCHIVE列作为主键的一部分。 But the problem here is that 2 rows can have same ID with different ARCHIVE column value. 但这里的问题是2行可以具有相同的ID和不同的ARCHIVE列值。 Actually thats not the main problem for us as 2 rows will be in different partitions. 实际上这不是我们作为2行的主要问题将在不同的分区。 Problem is when we will update the archive column value of one of them to other to move one of the row to archive partition, then it will not allow us to update the entry giving "Duplicate Error". 问题是当我们将其中一个的归档列值更新为其他行以将其中一个行移动到归档分区时,它将不允许我们更新给出“重复错误”的条目。

Can somebody help in this regard? 有人可以在这方面提供帮助吗?

Unfortunately, 不幸,

A UNIQUE INDEX (or a PRIMARY KEY ) must include all columns in the table's partitioning function UNIQUE INDEX (或PRIMARY KEY )必须包含表的分区功能中的所有列

and since MySQL does not support check constraints either, the only ugly workaround I can think of is enforcing the uniqueness manually though triggers: 而且由于MySQL也不支持检查约束,我能想到的唯一丑陋的解决方法是通过触发器手动强制执行唯一性:

CREATE TABLE t (
  id INT NOT NULL,
  archived TINYINT(1) NOT NULL DEFAULT 0,
  PRIMARY KEY (id, archived),  -- required by MySQL limitation on partitioning
)
PARTITION BY LIST(archived) (
  PARTITION pActive VALUES IN (0),
  PARTITION pArchived VALUES IN (1)
);

CREATE TRIGGER tInsert
BEFORE INSERT ON t FOR EACH ROW
CALL checkUnique(NEW.id);

CREATE TRIGGER tUpdate
BEFORE UPDATE ON t FOR EACH ROW
CALL checkUnique(NEW.id);

DELIMITER //
CREATE PROCEDURE checkUnique(pId INT)
BEGIN
  DECLARE flag INT;
  DECLARE message VARCHAR(50);
  SELECT id INTO flag FROM t WHERE id = pId;
  IF flag IS NOT NULL THEN
    -- the below tries to mimic the error raised
    -- by a regular UNIQUE constraint violation
    SET message = CONCAT("Duplicate entry '", pId, "'");
    SIGNAL SQLSTATE "23000" SET
      MYSQL_ERRNO = 1062,
      MESSAGE_TEXT = message,
      COLUMN_NAME = "id";
  END IF;
END //

( fiddle ) 小提琴

MySQL's limitations on partitioning being such a downer (in particular its lack of support for foreign keys), I would advise against using it altogether until the table grows so large that it becomes an actual concern. MySQL在分区方面的局限性如此下降(特别是它缺乏对外键的支持),我建议不要一直使用它,直到表变得如此之大以至于它成为一个真正的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM