我们知道,在达梦数据库中,一般情况,一行记录的长度,不能超过页大小的一半。也就是如果我们在初始化数据库的时候,如果选择的页大小是8K ,那么我们一个表,一行记录的所有字段加起来,不能超过4K 。
如果超过,就会碰到无法插入,或者无法update 的事情,报错为:记录超长。
当我们选择的页大小为16K 或者32K ,同理(也就是限制为8K 或者16K )。
备注:大字段不参与上述计算。
我们前面已经介绍过,对于如果确实要存取超过限制长度的情况,也是有处理办法的:对这个表启用超长列:alter table username.tablename enable using long row;
备注:以前往往需要选择一个比较长的字符类型字段,更改为CLOB ,当有超长列这个功能后,就不需要用这种对应用不有好的方式了(因为调整字段类型,可能涉及到读取改字段的代码需要修改调整。)
诚如上面说的,但是有时候,我们执行某个update 或者insert 的时候, 明明对应行的记录,没有超过一半的页大小,或者也已经启用了超长列了,为什么还会碰到 记录超长的错误呢?
数据库版本:DM Database Server x64 V8.1.0.156-Build(2019.05.05-106384)SEC
环境:个人pc 环境
drop table test2 ;
create table test2 ( v1 varchar , v2 varchar , v3 varchar ) ;
alter table test2 enable using long row ;
create index idx_test2_2 on test2 ( v3 );
insert into test2 values ( '' , '' , dbms_random . string ( 'x' , 1543 )); -- 成功
insert into test2 values ( '' , '' , dbms_random . string ( 'x' , 1544 )); -- 记录超长
update test2 set v3=dbms_random . string ( 'x' , 1544 ) where v1 is null ; -- 记录超长
drop table test1 ;
create table test1 (v1 varchar );
create index idx_1 on test1 (v1 );
declare
a int ; b int ;
begin
for rs in 1 ..3000 LOOP
b=rs ;
declare
begin
insert into test1 values (dbms_random . string ( 'x' , rs ));
exception when others then
raise_application_error ( -20001 , substr ( a|| '--' ||rs|| ' 执行失败 , ' ||SQLCODE|| ' ' ||SQLERRM|| ' ' ||dbms_utility . format_error_backtrace , 1 , 400 ));
end ;
end loop ;
end ;
--1544 执行失败 , -2665 记录超长 -2665[-20001]: anonymous block line 8
select page (); --8192
drop table test1 ;
create table test1 ( v1 varchar , v2 varchar , v3 varchar );
insert into test1 values (
dbms_random . string ( 'x' , 4000 ), '' , ''
); -- 记录超长
declare
a int ;
begin
for rs in 1 .. 1000 LOOp
declare begin
a=rs ;
insert into test1 values (
dbms_random . string ( 'x' , 3500+rs ), '' , ''
); -- 记录超长
exception when others then
raise_application_error ( -20001 , substr ( a|| ' 执行失败 , ' ||SQLCODE|| ' ' ||SQLERRM|| ' ' ||dbms_utility . format_error_backtrace , 1 , 400 ));
end ;
end loop ;
end ;
-- 380 执行失败 , -2665 记录超长 -2665[-20001]: anonymous block line 9
-- 3880 就无法插入了
insert into test1 values (
dbms_random . string ( 'x' , 3880 ), '' , ''
); -- 记录超长
insert into test1 values (
dbms_random . string ( 'x' , 3879 ), '' , ''
); -- 成功
alter table test1 enable using long row ;
insert into test1 values (
dbms_random . string ( 'x' , 3880 ), '' , ''
); -- 成功
insert into test1 values (
dbms_random . string ( 'x' , 3880 ), '' , ''
); -- 成功
insert into test1 values (
dbms_random . string ( 'x' , 3880 ), dbms_random . string ( 'x' , 1544 ), dbms_random . string ( 'x' , 1543 )
); -- 成功
create index idx_test1_1 on test1 ( v2 ); -- 记录超长
create index idx_test1_2 on test1 ( v3 ); -- 成功
其实,就是索引有长度限制。字符数通过varchar 类型,限制为1543 个字符,实际上,一个索引结构的最大长度,可能是3000 个字节,去掉一些存储结构本身占用的空间,结果就如上测试。
如果我们要解决【问题场景构建】中的问题,需要删除索引——也就是说,不要在过长的列上建立索引——一个索引涉及到的所有列,总长度不能超过设定的长度。
至少目前看起来,在过于长的列上,建立的索引,应用需要的程度很低。也就是说,该限制在达梦的正常使用过程中,暂时未发现会造成实质性影响。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69949798/viewspace-2683276/ ,如需转载,请注明出处,否则将追究法律责任。