最近维护库表的时候经常遇到字段长度超出唯一约束字段最大长度的报错,例如:
Warning! The maximum key length is 900 bytes. The index ‘testa$BPK_AK_Key’ has maximum length of 8003 bytes. For some combination of large values, the insert/update operation will fail.
下面分享下笔者关于这个问题的思考和解决方法。
临时的解决方法
当时的做法是:
- 和需求方沟通,能否更换唯一约束的相关字段,答复是由于业务的特殊性,不能更换唯一约束字段;
- 由于实际字段内容很长(4000以上),但判断唯一性并不需要全部字段,所以增加了一个字段,取该字段的一部分,然后用该字段来做唯一约束;
关于唯一约束这个问题,当时思考的解决方法有三个:
- 数据库层面唯一约束,但是字段长度有限制(用字段一部分做唯一约束有隐患);
- 程序层面,先查后插;
- 数据直接入库,后续校验剔除。
优劣:
方法一从效率和实时性角度来说是最快的,但是对唯一约束的字段要求比较高,最好能做到短小精悍,避免内容作ID;
方法二会减慢入库速度,而且字段过长也无法建立索引,随着数据的增长,入库速度会越来越慢;
方法三会存在及时性问题。
后续反思还是想从数据库角度做一些优化
这个问题的从数据角度出发其实就是如何高效的生成长字段的ID,联想到以前用来做字段加密的MD5,打算尝试下生成字符串的HASH值,用HASH值来做唯一约束。
效率测试
set statistics time on
set statistics io on
--创建测试表
if(object_id('testa') is not null )
drop table testa
GO
create table testa (
[ID] bigint IDENTITY(1,1) NOT NULL PRIMARY KEY,
[CODE] nvarchar(MAX) NOT NULL ,
[CODE_ID] varchar(32) NOT NULL ,
[DATE_VAL] date NULL
)
--Insert 100000rows DATA
insert