再談記錄超長
再談記錄超長
現象描述
我們知道,在達夢資料庫中,一般情況,一行記錄的長度,不能超過頁大小的一半。也就是如果我們在初始化資料庫的時候,如果選擇的頁大小是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部落格 ” ,連結:http://blog.itpub.net/69949798/viewspace-2683276/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Web 安全恩仇錄:再談邏輯漏洞Web
- 長期記錄
- 再談vbo
- 再談:資料治理的長效運營機制!
- 老生常談之再談this
- 2020再談跨域跨域
- 再談ERP選型
- Javascript繼承,再談JavaScript繼承
- 《無盡航線》製作人訪談記錄
- Next.js踩坑入門系列(三)— 目錄重構&&再談路由JS路由
- MySql先分組統計總記錄數,再獲取記錄數中的最大值MySql
- 再談java列舉enumJava
- 再談原始碼閱讀原始碼
- 再談 PHP 未來之路PHP
- 再談synchronized鎖升級synchronized
- 再談冪等機制
- css記錄1:文字塊內超長只顯示一行,且超過寬度顯示為省略號CSS
- 先驅者? 革新者? 再談《超級馬力歐64》的設計魅力
- 再談Windows訊息迴圈Windows
- 再談RTS(上):RTS的衰落
- 再談小型機:前景黯淡?非也!
- 再談前後端分離後端
- 超實用的SpringAOP實戰之日誌記錄Spring
- MySQL單表最大記錄數不能超過多少?MySql
- C#發票識別介面,再長的稅號錄入都不怕C#
- 給傻逼文學社長戴孝的長期記錄帖
- 再談23種設計模式(3):行為型模式(學習筆記)設計模式筆記
- 虛幻5降臨!再談談它的“黑科技”
- 記錄一些很酷的套路,有時間再展開寫
- 再談量化策略失效的問題
- 來吧!再談多執行緒執行緒
- 再談領域驅動設計
- 新手分享_再談FS暫存器
- 淺談超快讀與超快寫
- 從資料庫的角度談-元組(Tuple)和記錄(record)資料庫
- JVM系列之:再談java中的safepointJVMJava
- 再談前後端API簽名安全?後端API
- 再談函式和一等公民函式