ITPub博客

首页 > 数据库 > 国内数据库 > 再谈记录超长

再谈记录超长

原创 国内数据库 作者:yanhengdoudou 时间:2020-04-20 17:40:40 1 删除 编辑

 

  再谈记录超长

  现象描述

我们知道,在达梦数据库中,一般情况,一行记录的长度,不能超过页大小的一半。也就是如果我们在初始化数据库的时候,如果选择的页大小是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 ; -- 记录超长

  一次解析:实验1,- 索引长度测试

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/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-09-29

  • 博文量
    70
  • 访问量
    193340