在达梦数据库中:
达梦一个核心设计:表就是索引,索引就是表。
达梦默认创建的是索引组织表(IOT) 。这意味着表的数据本身就是一棵巨大的B+树(聚集索引),所有数据行都存放在这棵树的叶子节点上。
因此,任何达梦表(非堆表)必须且只能有一个聚集索引来组织物理存储。这个“组织者”可以是:
| 对比维度 | 聚集主键 (CLUSTER PRIMARY KEY) | 普通主键 (NON CLUSTER PRIMARY KEY) |
|---|---|---|
| 物理存储 | 决定物理顺序:数据行按主键值的顺序排列并存储。 | 不决定存储:数据的物理顺序由ROWID决定。 |
| 表数据组织者 | 主键列。数据存储的B+树直接以主键值作为Key构建。 | 隐藏列ROWID。系统自动创建一个以ROWID为Key的聚集索引来存储数据。 |
| 查询性能 | 主键查询极快:直接在主键B+树上就能找到所有列数据,无需额外操作(即不回表)。 | 主键查询需回表:先通过主键索引找到对应的ROWID,再根据ROWID去表的聚集索引中找到完整数据行(即回表)。 |
| 唯一性 | 保证主键列值唯一。 | 保证主键列值唯一。 |
| 数量限制 | 一个表有且只有一个聚集索引(无论是主键还是手动指定的)。 | 一个表可以有很多个(普通主键就是一个带唯一约束的非聚集索引)。 |
| 适用场景 | 经常通过主键进行精确查询或范围扫描的表(如订单表查订单详情)。 | 主键无业务含义(如自增ID),或频繁通过其他列查询,希望由该列来组织数据存储。 |
既然聚集主键查询更快,为什么不默认用它?
这背后是达梦为了兼容性和灵活性做出的取舍,完全由PK_WITH_CLUSTER参数控制(默认为0,即非聚集)。
主要原因有两个:
如果你明确需要让数据按主键存储,在建表时使用CLUSTER PRIMARY KEY关键字即可:
sql
-- 创建一个以STUNO列为聚集索引主键的表
CREATE TABLE STUDENT(
STUNO INT CLUSTER PRIMARY KEY, -- 这就是聚集主键
STUNAME VARCHAR(15) NOT NULL
);
如果你希望所有新创建的表,默认主键就是聚集主键(像MySQL InnoDB一样),可以修改参数:
sql
-- 查询当前设置
SELECT * FROM V$DM_INI WHERE PARA_NAME = 'PK_WITH_CLUSTER';
-- 动态修改参数,使之后创建的主键默认为聚集主键 (需相应权限)
ALTER SYSTEM SET 'PK_WITH_CLUSTER' = 1 BOTH;
设置后,普通的PRIMARY KEY就会自动变成聚集主键。
想知道一张表的数据到底是以什么作为聚集索引组织的?可以查询系统表:
sql
-- 查看表的主键是否为聚集索引
SELECT
T.TABLE_NAME,
I.INDEX_NAME,
I.UNIQUE_FLAG,
I.CLUSTER_FLAG -- 1表示聚集索引
FROM
USER_TABLES T
JOIN USER_INDEXES I ON T.TABLE_NAME = I.TABLE_NAME
WHERE
T.TABLE_NAME = 'YOUR_TABLE_NAME';
建议:
达梦社区技术 https://eco.dameng.com
文章
阅读量
获赞
