为什么会发生错误8349?虽然索引包括了一个Varchar(2000)类型的字段,但数据的长度并没有超过1024字节,怎样解决这个问题呢?(From DBMR1811)
(1). 首先,当创建一个包含varchar类型字段的索引时,DBMaster不会检查出索引的长度。
例如:
dmSQL> create table dbmr1811(id SERIAL(1),application_name VARCHAR(2000) default null );
dmSQL> create index idx_dbmr1811 on dbmr1811 (application_name);
以上的idx_dbmr1811包含了一个长度超过1024的varchar(2000)字段,但是能够成功创建索引,原因是DBMaster直到使用这个索引时,才检验它的长度。
(2). 当使用以上的索引时,DBMaster将根据不同的执行计划检验部分索引的长度。当一个执行计划使用嵌套连接时,它不知道这个数据的长度,所以它将会使用varchar类型的定义长度(在此处为2000字节)作为数据长度来分配缓存。当检验长度时,如果发现索引长度1024字节时,就会返回错误8394。
例如:
dmSQL> create table c1(a1 VARCHAR(2000) default null );
dmSQL> create index idx_c1 on c1 ( a1 );
dmSQL> create table d1(a1 VARCHAR(2000) default null );
dmSQL> create index idx_d1 on d1 ( a1 );
dmSQL> select * from c1 JOIN d1 on c1.a1 = d1.a1 where 1=1;
ERROR (8349): [DBMaster] total length of index key exceeds maximum length (1024 Bytes)
(3).有两种方法可以避免这种情况。
一种是执行“update statistics”。在执行“update statistics”之后,执行计划使用合并连接并且varchar的长度是实际长度并非定义的长度。
另一个方法是在表中使用强制合并连接。DBMaster4.3提供了强制优化的语法;你可以使用“MERGE JOIN…”语法让查询运行,然后使用“MERGE JOIN…”,并非Nested JOIN进行。
例如:
dmSQL> select * from c1 MERGE JOIN d1 on c1.a1 = d1.a1 where 1=1;
(4). 请注意,尽管成功地创建了这个类型索引(包括varchar类型字段),但插入的数据不能超过1024字节。
(5). 您最好不要在长字段建立普通索引。这种类型的索引将占用过多的索引页并且查询时有可能不被使用。所以我们建议用户在长字段创建全文索引。