上篇我们遇到了困难,主要是分区字段必须加入到主键列表,还有唯一索引组合中,否则不让我们建索引! 很多朋友说是为了保证唯一性? 因为分区分成了多个物理表,无法保证全局唯一,只能局部唯一性!
这是对的吗? 我们来做实验证实下看看
CREATE TABLE books.`dba_unique_test`
(
`Id` bigint(20) NOT NULL AUTO_INCREMENT,
`Money` decimal(20,2) NOT NULL,
`status` smallint(3) NOT NULL ,
`flow_no` varchar(33) NOT NULL COMMENT '流水号',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`Id`,create_time)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='流水表'
PARTITION BY RANGE (TO_DAYS(create_time))
(
PARTITION create_time_20200826 VALUES LESS THAN (738028) ENGINE = InnoDB,
PARTITION create_time_20200902 VALUES LESS THAN (738035) ENGINE = InnoDB,
PARTITION create_time_20200909 VALUES LESS THAN (738042) ENGINE = InnoDB,
PARTITION create_time_20200916 VALUES LESS THAN (738049) ENGINE = InnoDB,
PARTITION create_time_20200923 VALUES LESS THAN (738056) ENGINE = InnoDB,
PARTITION create_time_20200930 VALUES LESS THAN (738063) ENGINE = InnoDB,
PARTITION create_time_20201007 VALUES LESS THAN (738070) ENGINE = InnoDB,
PARTITION create_time_20201014 VALUES LESS THAN (738077) ENGINE = InnoDB,
PARTITION create_time_20201021 VALUES LESS THAN (738084) ENGINE = InnoDB,
PARTITION create_time_20201028 VALUES LESS THAN (738091) ENGINE = InnoDB,
PARTITION create_time_20201104 VALUES LESS THAN (738098) ENGINE = InnoDB,
PARTITION create_time_20201111 VALUES LESS THAN (738105) ENGINE = InnoDB,
PARTITION create_time_20201118 VALUES LESS THAN (738112) ENGINE = InnoDB,
PARTITION create_time_20201125 VALUES LESS THAN (738119) ENGINE = InnoDB,
PARTITION create_time_20201202 VALUES LESS THAN (738126) ENGINE = InnoDB,
PARTITION create_time_20201209 VALUES LESS THAN (738133) ENGINE = InnoDB,
PARTITION create_time_20210106 VALUES LESS THAN (738161) ENGINE = InnoDB,
PARTITION create_time_20210113 VALUES LESS THAN (738168) ENGINE = InnoDB,
PARTITION create_time_20210120 VALUES LESS THAN (738175) ENGINE = InnoDB,
PARTITION create_time_20210127 VALUES LESS THAN (738182) ENGINE = InnoDB,
PARTITION create_time_DEFAULTE VALUES LESS THAN MAXVALUE
);
然后造一点数据
--1 造数据
insert into dba_unique_test
(Id, amount, status, flow_no, create_time, update_time) VALUES
(1, 30.00, 1, '001', '2021/9/2 17:08:45', '2021/9/2 17:08:45'),
(2, 40.00, 2, '002', '2021/9/2 17:09:09', '2021/9/2 17:09:09'),
(3, 50.00, 1, '003', '2021/9/2 17:09:29', '2021/9/2 17:09:29');
--2 插入重复的ID 可以的
insert into dba_unique_test (Id, amount, status, flow_no) VALUES (1, 30.00, 1, '003');

--3 插入 ID+TIME 重复值 是不可以的。 说明主键冲突
insert into dba_unique_test
(Id, amount, status, flow_no, create_time, update_time) VALUES
(1, 30.00, 1, '001', '2021/9/2 17:08:45', '2021/9/2 17:08:45');

--4 创建联合唯一索引 ID+TIME 在ID有重复下 是可以的
CREATE UNIQUE INDEX `idx_id_time` USING BTREE ON books.dba_unique_test (id, create_time);
我觉得 加入分区字段 不是为了判断唯一性,你看我上面实验 就无法判断唯一性,主键加入分区字段 好理解 就是为了定位分区
--6 创建FLOW+time唯一索引 看能否保证唯一性
--目前数据如下 可以看出 FLOW_NO + CREATE_TIME 是没有重复值的
Id amount status flow_no create_time update_time
1 30.00 1 001 2021/9/2 17:08:45 2021/9/2 17:08:45
1 30.00 1 003 2021/9/2 17:11:10 2021/9/2 17:11:10
1 30.00 1 003 2021/9/2 17:20:03 2021/9/2 17:20:03
2 40.00 2 002 2021/9/2 17:09:09 2021/9/2 17:09:09
3 50.00 1 003 2021/9/2 17:09:29 2021/9/2 17:09:29
CREATE UNIQUE INDEX `idx_flow_time` USING BTREE ON dba_test_big_table_source.dba_unique_test (flow_no, create_time);
--居然成功了 那么它遵循了标准定义 也就是FLOW_NO+TIME的双值相同才会冲突。
--7 单独建唯一索引
CREATE UNIQUE INDEX `idx_uq_flow` USING BTREE ON books.dba_unique_test (flow_no);
"Lookup Error - MySQL Database Error: A UNIQUE INDEX must include all columns in the table's partitioning function"
--8 普通索引
CREATE INDEX `idx_btree_flow` USING BTREE ON books.dba_unique_test (flow_no);
是OK
这就奇怪 唯一索引强制加入分区字段 为了什么?无法保证唯一性 如果是为了提高效率,为什么其他非唯一是不用添加的,逼定二级索引的VALUE是指向主键的,而且主键包含了分区字段。
结论就是 无法保证唯一, 无论是全局还是本地都无法保证原来的唯一性.
至于为什么强制 加入唯一索引和主键呢? 请大家留言
文章转载自海鲨数据库架构师,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




