目錄
1、PK_WITH_CLUSTER取值為0
2、PK_WITH_CLUSTER取值為1
達夢數據庫的參數PK_WITH_CLUSTER在最近使用過程中發現與前期使用的版本存在差異,特此測試分析一下。具體哪個版本改動的暫未得知。
PK_WITH_CLUSTER,默認值為0,動態會話級參數。
參數含義:在建表語句或增加約束語句中指定主關鍵字時,是否缺省指定為CLUSTER,0:不指定;1:指定
注:該參數對水平分區表、列存儲表和堆表無效
測試版本:
1-3-26-2024.08.21-240039-20046-ENT
--03134284058-20240821-240039-20046 Pack37
接下來創建表,做一些驗證測試。本文使用創建聚集主鍵的方式來做測試,創建聚集索引的效果與之相同。
1、PK_WITH_CLUSTER取值為0
(1)使用SQL語句創建普通表,表中存在主鍵,建表正常無報錯
--創建一張普通測試表
DROP TABLE IF EXISTS T1;
CREATE TABLE T1(
ID INTEGER,
NAME VARCHAR(30),
AGE INT,
ORD INT,
PRIMARY KEY(ID)
);
--插入測試數據
INSERT INTO T1 VALUES (7,'A',15,1);
INSERT INTO T1 VALUES (1,'A',20,2);
INSERT INTO T1 VALUES (3,'A',53,3);
INSERT INTO T1 VALUES (5,'A',35,4);
INSERT INTO T1 VALUES (10,'A',62,5);
INSERT INTO T1 VALUES (6,'A',18,6);
INSERT INTO T1 VALUES (2,'A',35,7);
INSERT INTO T1 VALUES (4,'A',66,8);
INSERT INTO T1 VALUES (9,'A',24,9);
INSERT INTO T1 VALUES (8,'A',41,10);
COMMIT;
創建表后查看其表定義,由于PK_WITH_CLUSTER為0,所以建表后主鍵自動加了not cluster,建表結果與期望效果一致。
表數據默認以ROWID有序聚集。
(2)創建一張帶有大字段的普通表,表中存在主鍵,主鍵字段非大字段類型,建表正常無報錯
--創建一張普通測試表
DROP TABLE IF EXISTS T2;
CREATE TABLE T2(
ID INTEGER,
NAME VARCHAR(30),
AGE INT,
ORD INT,
DINFO CLOB,
PRIMARY KEY(ID)
);
--插入測試數據
INSERT INTO T2 VALUES (7,'A',15,1,'test');
INSERT INTO T2 VALUES (1,'A',20,2,'test');
INSERT INTO T2 VALUES (3,'A',53,3,'test');
INSERT INTO T2 VALUES (5,'A',35,4,'test');
INSERT INTO T2 VALUES (10,'A',62,5,'test');
INSERT INTO T2 VALUES (6,'A',18,6,'test');
INSERT INTO T2 VALUES (2,'A',35,7,'test');
INSERT INTO T2 VALUES (4,'A',66,8,'test');
INSERT INTO T2 VALUES (9,'A',24,9,'test');
INSERT INTO T2 VALUES (8,'A',41,10,'test');
COMMIT;
創建表后查看其表定義,由于PK_WITH_CLUSTER為0,所以建表后主鍵自動加了not cluster,建表結果與期望效果一致。
表數據默認以ROWID有序聚集。
(3)創建一張帶有大字段的普通表,表中存在主鍵,主鍵字段為大字段類型,建表報錯
--創建一張普通測試表
DROP TABLE IF EXISTS T3;
CREATE TABLE T3(
ID INTEGER,
NAME VARCHAR(30),
AGE INT,
ORD INT,
DINFO CLOB,
PRIMARY KEY(DINFO)
);
報錯信息:“字段[DINFO]不可比較”。
這里可能會聯想到一個參數ENABLE_BLOB_CMP_FLAG(是否支持大字段類型的比較)。但實際將參數ENABLE_BLOB_CMP_FLAG改為1后也是會繼續報錯的,因為此參數的作用主要是解決SQL語句中大字段與字符類型的比較這種情況的。
報錯原因:大字段本身是不支持比較的,在大字段上創建主鍵,其實就相當于對大字段創建唯一素索引,為了確保數據的唯一,會涉及到比較的過程,所以報錯。
(4)?創建一張帶有大字段的普通表,建表時使用cluster顯式創建聚集主鍵,主鍵字段為大字段類型,建表報錯
--創建一張普通測試表
DROP TABLE IF EXISTS T4;
CREATE TABLE T4(
ID INTEGER,
NAME VARCHAR(30),
AGE INT,
ORD INT,
DINFO CLOB,
CLUSTER PRIMARY KEY(DINFO)
);
報錯信息:“字段[DINFO]不可比較”。
報錯原因:與上述(3)的原因相同。
(5)創建一張普通表,建表時使用cluster顯式創建聚集主鍵,建表正常無報錯
--創建一張普通測試表
DROP TABLE IF EXISTS T5;
CREATE TABLE T5(
ID INTEGER,
NAME VARCHAR(30),
AGE INT,
ORD INT,
CLUSTER PRIMARY KEY(ID)
);
--插入測試數據
INSERT INTO T5 VALUES (7,'A',15,1);
INSERT INTO T5 VALUES (1,'A',20,2);
INSERT INTO T5 VALUES (3,'A',53,3);
INSERT INTO T5 VALUES (5,'A',35,4);
INSERT INTO T5 VALUES (10,'A',62,5);
INSERT INTO T5 VALUES (6,'A',18,6);
INSERT INTO T5 VALUES (2,'A',35,7);
INSERT INTO T5 VALUES (4,'A',66,8);
INSERT INTO T5 VALUES (9,'A',24,9);
INSERT INTO T5 VALUES (8,'A',41,10);
COMMIT;
創建表后查看其表定義,由于顯式指定了cluster,所以實際創建的聚集主鍵,建表結果與期望效果一致。
表數據以主鍵字段“ID”有序聚集。
(6)創建一張帶有大字段的普通表,建表時使用cluster顯式創建聚集主鍵,主鍵字段非大字段類型,建表正常無報錯
--創建一張普通測試表
DROP TABLE IF EXISTS T6;
CREATE TABLE T6(
ID INTEGER,
NAME VARCHAR(30),
AGE INT,
ORD INT,
DINFO CLOB,
CLUSTER PRIMARY KEY(ID)
);
--插入測試數據
INSERT INTO T6 VALUES (7,'A',15,1,'test');
INSERT INTO T6 VALUES (1,'A',20,2,'test');
INSERT INTO T6 VALUES (3,'A',53,3,'test');
INSERT INTO T6 VALUES (5,'A',35,4,'test');
INSERT INTO T6 VALUES (10,'A',62,5,'test');
INSERT INTO T6 VALUES (6,'A',18,6,'test');
INSERT INTO T6 VALUES (2,'A',35,7,'test');
INSERT INTO T6 VALUES (4,'A',66,8,'test');
INSERT INTO T6 VALUES (9,'A',24,9,'test');
INSERT INTO T6 VALUES (8,'A',41,10,'test');
COMMIT;
創建表后查看其表定義,因為顯式指定了cluster,理論上這里應該是聚集主鍵,但實際創建的非聚集主鍵,建表結果與期望效果并不一致,在比較老的版本上這里應該是cluster primary。
原因分析:?在達夢數據庫中,有大字段的表是不建議創建聚集索引的,因為可能存在數據文件快速膨脹的風險。所以這里應該是基于這一點,內部自動進行了轉換,創建為了非聚集主鍵。
因此,表數據仍然以默認的ROWID有序聚集。
(7)創建一張分區表,表中存在主鍵,建表正常無報錯
--創建一張普通測試表
DROP TABLE IF EXISTS T7;
CREATE TABLE T7(
ID INTEGER,
NAME VARCHAR(30),
AGE INT,
ORD INT,
PRIMARY KEY(ID)
)
PARTITION BY RANGE(AGE) INTERVAL(10)(
PARTITION P1 VALUES EQU OR LESS THAN (18),
PARTITION P2 VALUES EQU OR LESS THAN (35),
PARTITION P3 VALUES EQU OR LESS THAN (60),
PARTITION P4 VALUES EQU OR LESS THAN (100));
--插入測試數據
INSERT INTO T7 VALUES (7,'A',15,1);
INSERT INTO T7 VALUES (1,'A',20,2);
INSERT INTO T7 VALUES (3,'A',53,3);
INSERT INTO T7 VALUES (5,'A',35,4);
INSERT INTO T7 VALUES (10,'A',62,5);
INSERT INTO T7 VALUES (6,'A',18,6);
INSERT INTO T7 VALUES (2,'A',35,7);
INSERT INTO T7 VALUES (4,'A',66,8);
INSERT INTO T7 VALUES (9,'A',24,9);
INSERT INTO T7 VALUES (8,'A',41,10);
COMMIT;
創建表后查看其表定義,由于PK_WITH_CLUSTER為0,所以建表后主鍵自動加了not cluster,建表結果與期望效果一致。
各子分區表中,表數據默認以ROWID有序聚集。
(8)創建一張分區表,建表時使用cluster顯式創建聚集主鍵,建表報錯
--創建一張普通測試表
DROP TABLE IF EXISTS T8;
CREATE TABLE T8(
ID INTEGER,
NAME VARCHAR(30),
AGE INT,
ORD INT,
CLUSTER PRIMARY KEY(ID)
)
PARTITION BY RANGE(AGE) INTERVAL(10)(
PARTITION P1 VALUES EQU OR LESS THAN (18),
PARTITION P2 VALUES EQU OR LESS THAN (35),
PARTITION P3 VALUES EQU OR LESS THAN (60),
PARTITION P4 VALUES EQU OR LESS THAN (100));
報錯信息:“聚集主鍵必須包含全部分區列”
報錯原因:創建聚集主鍵時,主鍵中需要把分區字段也加上
(9)創建一張分區表,建表時使用cluster顯式創建聚集主鍵,聚集主鍵包含分區字段,建表正常無報錯
--創建一張普通測試表
DROP TABLE IF EXISTS T8;
CREATE TABLE T8(
ID INTEGER,
NAME VARCHAR(30),
AGE INT,
ORD INT,
CLUSTER PRIMARY KEY(ID,AGE)
)
PARTITION BY RANGE(AGE) INTERVAL(10)(
PARTITION P1 VALUES EQU OR LESS THAN (18),
PARTITION P2 VALUES EQU OR LESS THAN (35),
PARTITION P3 VALUES EQU OR LESS THAN (60),
PARTITION P4 VALUES EQU OR LESS THAN (100));
--插入測試數據
INSERT INTO T8 VALUES (7,'A',15,1);
INSERT INTO T8 VALUES (1,'A',20,2);
INSERT INTO T8 VALUES (3,'A',53,3);
INSERT INTO T8 VALUES (5,'A',35,4);
INSERT INTO T8 VALUES (10,'A',62,5);
INSERT INTO T8 VALUES (6,'A',18,6);
INSERT INTO T8 VALUES (2,'A',35,7);
INSERT INTO T8 VALUES (4,'A',66,8);
INSERT INTO T8 VALUES (9,'A',24,9);
INSERT INTO T8 VALUES (8,'A',41,10);
COMMIT;
創建表后查看其表定義,由于顯式指定了cluster,所以實際創建的聚集主鍵,建表結果與期望效果一致。
各子分區表中,表數據以主鍵字段“ID”,“AGE”有序聚集。數據會先以ID排序,當ID相同時按照AGE排序。
(10)創建一張帶有大字段的分區表,表中存在主鍵,建表正常無報錯
--創建一張普通測試表
DROP TABLE IF EXISTS T10;
CREATE TABLE T10(
ID INTEGER,
NAME VARCHAR(30),
AGE INT,
ORD INT,
DINFO CLOB,
CLUSTER PRIMARY KEY(ID)
)
PARTITION BY RANGE(AGE) INTERVAL(10)(
PARTITION P1 VALUES EQU OR LESS THAN (18),
PARTITION P2 VALUES EQU OR LESS THAN (35),
PARTITION P3 VALUES EQU OR LESS THAN (60),
PARTITION P4 VALUES EQU OR LESS THAN (100));
--插入測試數據
INSERT INTO T10 VALUES (7,'A',15,1,'test');
INSERT INTO T10 VALUES (1,'A',20,2,'test');
INSERT INTO T10 VALUES (3,'A',53,3,'test');
INSERT INTO T10 VALUES (5,'A',35,4,'test');
INSERT INTO T10 VALUES (10,'A',62,5,'test');
INSERT INTO T10 VALUES (6,'A',18,6,'test');
INSERT INTO T10 VALUES (2,'A',35,7,'test');
INSERT INTO T10 VALUES (4,'A',66,8,'test');
INSERT INTO T10 VALUES (9,'A',24,9,'test');
INSERT INTO T10 VALUES (8,'A',41,10,'test');
COMMIT;
這里問題就出現了,建表的語句中聚集主鍵沒有加分區字段,但是為什么創建沒有報錯呢?以往的老版本上,這里應該也會報錯“聚集主鍵必須包含全部分區列”才對。
查看表定義,發現這里并沒有創建成聚集主鍵,數據庫自動加了not cluster,建表結果與期望效果不一致。
原因分析:這里應該是與(6)的測試情況是一樣的原因,表中因為含有了大字段,所以系統內部自動創建成了非聚集主鍵。
由于最終創建的還是非聚集主鍵,數據還是默認以rowid排序聚集的。
(11)創建一張帶有大字段的分區表,建表時使用cluster顯式創建聚集主鍵,聚集主鍵包含分區字段,建表正常無報錯
--創建一張普通測試表
DROP TABLE IF EXISTS T11;
CREATE TABLE T11(
ID INTEGER,
NAME VARCHAR(30),
AGE INT,
ORD INT,
DINFO CLOB,
CLUSTER PRIMARY KEY(ID,AGE)
)
PARTITION BY RANGE(AGE) INTERVAL(10)(
PARTITION P1 VALUES EQU OR LESS THAN (18),
PARTITION P2 VALUES EQU OR LESS THAN (35),
PARTITION P3 VALUES EQU OR LESS THAN (60),
PARTITION P4 VALUES EQU OR LESS THAN (100));
--插入測試數據
INSERT INTO T11 VALUES (7,'A',15,1,'test');
INSERT INTO T11 VALUES (1,'A',20,2,'test');
INSERT INTO T11 VALUES (3,'A',53,3,'test');
INSERT INTO T11 VALUES (5,'A',35,4,'test');
INSERT INTO T11 VALUES (10,'A',62,5,'test');
INSERT INTO T11 VALUES (6,'A',18,6,'test');
INSERT INTO T11 VALUES (2,'A',35,7,'test');
INSERT INTO T11 VALUES (4,'A',66,8,'test');
INSERT INTO T11 VALUES (9,'A',24,9,'test');
INSERT INTO T11 VALUES (8,'A',41,10,'test');
COMMIT;
查看表定義,這里一樣沒有創建成聚集主鍵,盡管滿足了“聚集主鍵必須包含全部分區列”的限制,但大字段數據類型帶來的風險更嚴重,因此還是優先保證規避風險,所以數據庫還是自動加了not cluster,建表結果與期望效果不一致。
同樣是由于創建的非聚集主鍵,數據還是默認以rowid排序聚集的。
(12)創建一張帶有大字段的分區表, 表中存在主鍵或聚集主鍵,且主鍵或聚集主鍵是大字段,或者主鍵或聚集主鍵包含大字段的情況,均會報錯。
--報錯,分區表,主鍵為大字段
--創建一張普通測試表
DROP TABLE IF EXISTS T12;
CREATE TABLE T12(
ID INTEGER,
NAME VARCHAR(30),
AGE INT,
ORD INT,
DINFO CLOB,
PRIMARY KEY(DINFO)
)
PARTITION BY RANGE(AGE) INTERVAL(10)(
PARTITION P1 VALUES EQU OR LESS THAN (18),
PARTITION P2 VALUES EQU OR LESS THAN (35),
PARTITION P3 VALUES EQU OR LESS THAN (60),
PARTITION P4 VALUES EQU OR LESS THAN (100));--報錯,分區表,聚集主鍵為大字段
--創建一張普通測試表
DROP TABLE IF EXISTS T12;
CREATE TABLE T12(
ID INTEGER,
NAME VARCHAR(30),
AGE INT,
ORD INT,
DINFO CLOB,
CLUSTER PRIMARY KEY(DINFO)
)
PARTITION BY RANGE(AGE) INTERVAL(10)(
PARTITION P1 VALUES EQU OR LESS THAN (18),
PARTITION P2 VALUES EQU OR LESS THAN (35),
PARTITION P3 VALUES EQU OR LESS THAN (60),
PARTITION P4 VALUES EQU OR LESS THAN (100));--報錯,分區表,主鍵含大字段
--創建一張普通測試表
DROP TABLE IF EXISTS T12;
CREATE TABLE T12(
ID INTEGER,
NAME VARCHAR(30),
AGE INT,
ORD INT,
DINFO CLOB,
PRIMARY KEY(ID,DINFO)
)
PARTITION BY RANGE(AGE) INTERVAL(10)(
PARTITION P1 VALUES EQU OR LESS THAN (18),
PARTITION P2 VALUES EQU OR LESS THAN (35),
PARTITION P3 VALUES EQU OR LESS THAN (60),
PARTITION P4 VALUES EQU OR LESS THAN (100));--報錯,分區表,聚集主鍵含大字段
--創建一張普通測試表
DROP TABLE IF EXISTS T12;
CREATE TABLE T12(
ID INTEGER,
NAME VARCHAR(30),
AGE INT,
ORD INT,
DINFO CLOB,
CLUSTER PRIMARY KEY(ID,DINFO)
)
PARTITION BY RANGE(AGE) INTERVAL(10)(
PARTITION P1 VALUES EQU OR LESS THAN (18),
PARTITION P2 VALUES EQU OR LESS THAN (35),
PARTITION P3 VALUES EQU OR LESS THAN (60),
PARTITION P4 VALUES EQU OR LESS THAN (100));--報錯,分區表,聚集主鍵包含全部分區列,且含大字段
--創建一張普通測試表
DROP TABLE IF EXISTS T12;
CREATE TABLE T12(
ID INTEGER,
NAME VARCHAR(30),
AGE INT,
ORD INT,
DINFO CLOB,
CLUSTER PRIMARY KEY(ID,AGE,DINFO)
)
PARTITION BY RANGE(AGE) INTERVAL(10)(
PARTITION P1 VALUES EQU OR LESS THAN (18),
PARTITION P2 VALUES EQU OR LESS THAN (35),
PARTITION P3 VALUES EQU OR LESS THAN (60),
PARTITION P4 VALUES EQU OR LESS THAN (100));
報錯原因與(3)測試的原因相同。
2、PK_WITH_CLUSTER取值為1
當PK_WITH_CLUSTER=1時,其實就是免去了顯式指定CLUSTER的方法,自動創建為了聚集主鍵或聚集索引,根據前文PK_WITH_CLUSTER取值為0時的測試結果及原因,其實可以猜到PK_WITH_CLUSTER取值為1時不同情況下的測試結果,因此這里直接寫實際測試結果,不再過多贅述各測試結果出現的原因。
(1)使用SQL語句創建普通表,表中存在主鍵,建表正常無報錯,創建的是聚集主鍵
(2)創建一張帶有大字段的普通表,表中存在主鍵,主鍵字段非大字段類型,建表正常無報錯,創建的是非聚集主鍵
(3)創建一張帶有大字段的普通表,表中存在主鍵,主鍵字段為大字段類型,建表報錯。報錯信息:“字段[DINFO]不可比較”
(4)創建一張帶有大字段的普通表,建表時使用cluster顯式創建聚集主鍵,主鍵字段為大字段類型,建表報錯。報錯信息:“字段[DINFO]不可比較”
(5)創建一張普通表,建表時使用cluster顯式創建聚集主鍵,建表正常無報錯,創建的是聚集主鍵
(6)創建一張帶有大字段的普通表,建表時使用cluster顯式創建聚集主鍵,主鍵字段非大字段類型,建表正常無報錯,創建的是非聚集主鍵
(7)創建一張分區表,表中存在主鍵,建表正常無報錯,創建的是非聚集主鍵
(8)創建一張分區表,建表時使用cluster顯式創建聚集主鍵,建表報錯。報錯信息:“聚集主鍵必須包含全部分區列”
(9)創建一張分區表,建表時使用cluster顯式創建聚集主鍵,聚集主鍵包含分區字段,建表正常無報錯,創建的是聚集主鍵
(10)創建一張帶有大字段的分區表,表中存在主鍵,建表正常無報錯,創建的是非聚集主鍵
(11)創建一張帶有大字段的分區表,建表時使用cluster顯式創建聚集主鍵,聚集主鍵包含分區字段,建表正常無報錯,創建的是非聚集主鍵
(12)創建一張帶有大字段的分區表, 表中存在主鍵或聚集主鍵,且主鍵或聚集主鍵是大字段,或者主鍵或聚集主鍵包含大字段的情況,均會報錯。報錯信息:“字段[DINFO]不可比較”
?
總結:達夢數據庫底層修改策略,使得無論參數PK_WITH_CLUSTER是否為1,無論是否指定CLUSTER關鍵字顯式創建聚集索引或聚集主鍵,目前均會自動避免出現聚簇表中有大字段的現象。此外,當參數PK_WITH_CLUSTER為1時,如果沒有顯式指定CLUSTER關鍵字,創建的分區表主鍵不滿足“包含全部分區列”的條件,會自動創建成非聚集主鍵。