上篇我们遇到了困难,主要是分区字段必须加入到主键列表,还有唯一索引组合中,否则不让我们建索引! 很多朋友说是为了保证唯一性? 因为分区分成了多个物理表,无法保证全局唯一,只能局部唯一性!
这是对的吗? 我们来做实验证实下看看
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进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
唯一性是指唯一索引字段数据的唯一性,你上面第一个id是普通自增索引,并不是唯一索引,自然允许重复。然后联和主键(ID+time)是必须唯一的,这里是id+time的值组合起来唯一吧,并不是说单个唯一也算的,所有ID单个唯一是允许的。假设分区键和主键是两个不同的列,在进行插入操作时,虽然也指定了分区键,但还是需要扫描所有分区才能判断插入的主键值是否违反了唯一性约束。可能考虑性能问题吧,牺牲了一定的灵活性,这样单独的唯一索引不允许存在了
2年前

评论
个人理解:
对range分区有一个好处,分区的列值连续时,插入一条新数据,判断是否满足唯一性约束,只需在一个分区里检查唯一性。
3年前

1
相关阅读
【MySQL 30周年庆】MySQL 8.0 OCP考试限时免费!教你免费领考券
墨天轮小教习
1626次阅读
2025-04-25 18:53:11
MySQL 30 周年庆!MySQL 8.4 认证免费考!这次是认真的。。。
严少安
622次阅读
2025-04-25 15:30:58
墨天轮个人数说知识点合集
JiekeXu
462次阅读
2025-04-01 15:56:03
MySQL数据库当前和历史事务分析
听见风的声音
447次阅读
2025-04-01 08:47:17
【活动】分享你的压箱底干货文档,三篇解锁进阶奖励!
墨天轮编辑部
391次阅读
2025-04-17 17:02:24
MySQL 9.3 正式 GA,我却大失所望,新特性亮点与隐忧并存?
JiekeXu
369次阅读
2025-04-15 23:49:58
3月“墨力原创作者计划”获奖名单公布
墨天轮编辑部
340次阅读
2025-04-15 14:48:05
openHalo问世,全球首款基于PostgreSQL兼容MySQL协议的国产开源数据库
严少安
316次阅读
2025-04-07 12:14:29
记录MySQL数据库的一些奇怪的迁移需求!
陈举超
211次阅读
2025-04-15 15:27:53
[MYSQL] 服务器出现大量的TIME_WAIT, 每天凌晨就清零了
大大刺猬
188次阅读
2025-04-01 16:20:44