DMDRS数据迁移:大字段表、无主键表与大数据量表的处理实践
1. 引言
在达梦数据库的 DMDRS 数据同步项目中,迁移前的表结构检查往往决定了同步的成败与效率。本文基于实际项目经验,系统梳理了三类需要重点关注的表:大字段表、无主键表和数据量过大的表,并给出对应的排查 SQL 与处理思路,帮助在同步前快速识别风险、合理规划装载批次。
2. 大字段表的识别与处理
2.1 什么是大字段表
在达梦数据库中,"大字段表"并非指数据量大的表,而是指表中包含大对象类型(LOB)字段,常见类型包括:
- BLOB:二进制大对象,常用于图片、文件、音视频等;
- CLOB:字符大对象,常用于超长文本、JSON/XML、文章正文等;
- TEXT:大文本类型,在同步迁移场景中通常也按大字段考虑。
例如:
CREATE TABLE TEST_LOB (
ID INT,
NAME VARCHAR(100),
DESCRIPTION CLOB,
FILE_DATA BLOB
);
该表包含 CLOB 和 BLOB 字段,因此属于大字段表。
2.2 查询大字段表的 SQL
按表查询:
SELECT OWNER, TABLE_NAME
FROM ALL_TAB_COLUMNS
WHERE DATA_TYPE IN ('BLOB', 'CLOB', 'TEXT')
AND OWNER NOT IN ('SYS', 'SYSJOB')
AND TABLE_NAME IN ('表名1', '表名2', ...);
按模式查询:
SELECT OWNER, TABLE_NAME, COLUMN_NAME, DATA_TYPE
FROM ALL_TAB_COLUMNS
WHERE DATA_TYPE IN ('BLOB', 'CLOB', 'TEXT')
AND OWNER IN ('模式1', '模式2');
查询逻辑:从 ALL_TAB_COLUMNS 中筛选字段类型为 BLOB/CLOB/TEXT 的列,排除系统模式,再限定到需要同步的表。
例如同步 STUDENTS、COURSES、SCORES 三张表:
SELECT OWNER, TABLE_NAME
FROM ALL_TAB_COLUMNS
WHERE DATA_TYPE IN ('BLOB', 'CLOB', 'TEXT')
AND OWNER NOT IN ('SYS', 'SYSJOB')
AND TABLE_NAME IN ('STUDENTS', 'COURSES', 'SCORES');
无返回结果说明这些表不含大字段;若返回 TESTEXP STUDENTS,则说明该表至少存在一个大字段列。如需进一步定位具体字段,可执行:
SELECT OWNER, TABLE_NAME, COLUMN_NAME, DATA_TYPE
FROM ALL_TAB_COLUMNS
WHERE DATA_TYPE IN ('BLOB', 'CLOB', 'TEXT')
AND OWNER NOT IN ('SYS', 'SYSJOB')
AND TABLE_NAME IN ('STUDENTS', 'COURSES', 'SCORES')
ORDER BY OWNER, TABLE_NAME, COLUMN_ID;
2.3 为什么大字段表需要关注
LOB 字段在装载、实时同步、网络传输和同步参数配置上通常需要额外关注,主要体现在:
- 装载和网络传输压力较大;
- 占用更多目标端存储与缓存资源;
- 同步参数可能需要针对 LOB 单独调优。
3. 无主键表的识别与处理
3.1 为什么有主键的表更适合同步
主键的核心作用是唯一确定一条数据。例如:
CREATE TABLE TESTEXP.STUDENTS (
STUDENT_ID INT PRIMARY KEY,
NAME VARCHAR(50),
AGE INT
);
源端执行 UPDATE 后,DMDRS 捕获日志并携带主键信息,目标端可直接通过 WHERE STUDENT_ID = 1001 快速定位到唯一记录。主键自带唯一索引,查找效率高。
3.2 无主键表的核心风险
无主键表在 UPDATE/DELETE 场景下缺少唯一标识。例如:
CREATE TABLE TESTEXP.TEST_NO_PK (
NAME VARCHAR(50),
AGE INT
);
若表中存在多行 NAME='ZHANG', AGE=20,源端修改其中一行时,DMDRS 到目标端执行 UPDATE/DELETE 时无法确定应操作哪一行,这就是无主键同步的核心风险。
DM8 的逻辑日志参数 RLOG_APPEND_LOGIC 可以体现这一区别:表存在主键时,UPDATE/DELETE 主要记录主键信息;无主键时则需要记录更多甚至全部列的信息。
3.3 无主键带来的三个问题
第一,UPDATE/DELETE 性能下降。 有主键时 DELETE 可走主键唯一索引快速定位;无主键时可能需要依赖多个普通字段组合定位,缺乏合适索引时容易扫描大量数据。对于几百万、几千万行的表,实时同步会明显变慢。
第二,可能无法唯一定位数据。 没有主键、唯一索引或可靠的 ROWID 映射时,可能出现 UPDATE 找不到数据、条件匹配多条记录、DELETE 无法准确定位原始记录等情况,最终导致源端与目标端数据不一致。
第三,可能拖慢同一同步组里的正常表。 若同步组中某张无主键表有大量 UPDATE/DELETE 且每次定位都很慢,会影响该组事务执行和整体入库性能。因此"无主键的表单独同步"更准确的理解是:将无主键/无唯一索引的表单独分组,不与普通有主键表混在同一个执行组中,避免拖累其他表。
3.4 查询无主键表
检查指定同步表是否有主键:
SELECT T.OWNER, T.TABLE_NAME
FROM ALL_TABLES T
WHERE T.OWNER = 'TESTEXP'
AND T.TABLE_NAME IN ('STUDENTS', 'COURSES', 'SCORES')
AND NOT EXISTS (
SELECT 1
FROM ALL_CONSTRAINTS C
WHERE C.OWNER = T.OWNER
AND C.TABLE_NAME = T.TABLE_NAME
AND C.CONSTRAINT_TYPE = 'P'
);
查询某个模式下所有无主键表:
SELECT T.OWNER, T.TABLE_NAME
FROM ALL_TABLES T
WHERE T.OWNER = 'TESTEXP'
AND NOT EXISTS (
SELECT 1
FROM ALL_CONSTRAINTS C
WHERE C.OWNER = T.OWNER
AND C.TABLE_NAME = T.TABLE_NAME
AND C.CONSTRAINT_TYPE = 'P'
)
ORDER BY T.TABLE_NAME;
3.5 更应关注:无主键且无唯一索引的表
DMDRS 真正关心的是能否高效、唯一定位一行数据。无主键并不等于完全没有唯一定位能力,例如:
CREATE TABLE T1 (
ID INT,
NAME VARCHAR(50)
);
CREATE UNIQUE INDEX IDX_T1_ID ON T1(ID);
该表虽无主键,但 ID 上有唯一索引,同步表现通常优于"主键、唯一索引都没有"的表。因此建议执行以下 SQL,找出真正需要重点关注的表:
SELECT T.OWNER, T.TABLE_NAME
FROM ALL_TABLES T
WHERE T.OWNER = 'TESTEXP'
-- 没有主键
AND NOT EXISTS (
SELECT 1
FROM ALL_CONSTRAINTS C
WHERE C.OWNER = T.OWNER
AND C.TABLE_NAME = T.TABLE_NAME
AND C.CONSTRAINT_TYPE = 'P'
)
-- 也没有唯一索引
AND NOT EXISTS (
SELECT 1
FROM ALL_INDEXES I
WHERE I.OWNER = T.OWNER
AND I.TABLE_NAME = T.TABLE_NAME
AND I.UNIQUENESS = 'UNIQUE'
)
ORDER BY T.TABLE_NAME;
4. 大数据量表的识别与单独装载
4.1 4000 万行是经验阈值而非硬性上限
需要明确:4000 万行不是 DMDRS 官方规定的硬性上限。官方强调的是"数据量大的表"需要采用分组装载、断点续传等方式。在现场同步数据过程中,将4000 万定义为当前现场判断是否为大表的标准,因此4000万时作为现场实施中的经验阈值。
4.2 为什么大表建议单独装载
第一,全量装载耗时明显增加。 大表装载需经历源端读取、DMDRS LOAD、网络传输、目标端接收、INSERT/快速装载、索引约束处理等环节,消耗源库磁盘 I/O、DMDRS CPU/内存/线程、网络带宽、目标库磁盘 I/O 与 CPU 缓存等资源。10 万行很快完成,4000 万行时间明显增长,1 亿行可能成为整个装载任务的瓶颈。
第二,全量装载时间越长,增量数据缓存越多。 DMDRS 添加同步表时,全量与增量数据可同时进入同步流程。全量装载完成前,目标端会先缓存该表产生的增量数据,装载完成后再激活执行。若 5000 万行装载 2 小时,期间业务持续产生变化,待处理的增量会不断累积,导致全量完成后同步延迟较长。
第三,大表可能影响其他普通表。 若一批装载中包含 8000 万行的大表,其占用大量装载线程、网络和数据库 I/O,可能影响同批其他表的装载。分批装载更便于控制资源、观察进度、处理异常、单独重装和调整并行度。
4.3 查询表数据行数
使用达梦官方提供的 TABLE_ROWCOUNT() 函数:
SELECT A.OWNER, A.TABLE_NAME,
TABLE_ROWCOUNT(A.OWNER, A.TABLE_NAME) AS ROW_COUNT
FROM ALL_TABLES A
WHERE A.OWNER = 'TESTEXP'
ORDER BY ROW_COUNT DESC;
只查询准备同步的表:
SELECT A.OWNER, A.TABLE_NAME,
TABLE_ROWCOUNT(A.OWNER, A.TABLE_NAME) AS ROW_COUNT
FROM ALL_TABLES A
WHERE A.OWNER = 'TESTEXP'
AND A.TABLE_NAME IN ('STUDENTS', 'COURSES', 'SCORES', 'USER_LOG', 'ORDER_HISTORY')
ORDER BY ROW_COUNT DESC;
直接筛选超过 4000 万行的表:
SELECT OWNER, TABLE_NAME, ROW_COUNT
FROM (
SELECT A.OWNER, A.TABLE_NAME,
TABLE_ROWCOUNT(A.OWNER, A.TABLE_NAME) AS ROW_COUNT
FROM ALL_TABLES A
WHERE A.OWNER = 'TESTEXP'
) T
WHERE ROW_COUNT > 40000000
ORDER BY ROW_COUNT DESC;
4.4 大表使用 GROUP 分组并行装载
对于普通表,可理解为"一张表一个整体装载";而大表使用 GROUP 后,可将一张大表按范围切分为多个部分并行装载。例如 8000 万行的表可切分为 0~1000 万、1000~2000 万等多个区间,由多个任务并行装载,提高效率并支持断点续传,降低故障重装成本。
5. 同步前检查清单与总结
5.1 三类风险表汇总
| 检查类型 | 检查内容 | 主要风险 | 处理思路 |
|---|---|---|---|
| 大字段表 | BLOB/CLOB/TEXT | 装载、网络、存储压力较大 | 重点关注,必要时单独装载 |
| 无主键表 | 无 PK/唯一索引 | UPDATE/DELETE 定位困难、性能差 | 单独分组或使用 ROWID 映射 |
| 大数据量表 | 超过 4000 万行(经验值) | 全量慢、增量积压、占用资源 | 单独装载 + GROUP 并行 |
5.2 同步前检查流程
源端数据库
↓
同步对象梳理
↓
① 查大字段表
↓
② 查无主键/无唯一索引表
↓
③ 查各表数据行数
↓
④ 筛选超过 4000 万行的大表
↓
⑤ 根据情况划分装载批次
↓
普通表 / 无主键表 / 大字段表 / 超大表
↓
全量装载 + 实时同步
5.3 核心结论
大表单独装载的目的,不是因为超过 4000 万行 DMDRS 就无法同步,而是为了避免大表长时间全量装载占用大量 I/O、网络和执行资源,同时减少装载期间持续产生的增量数据积压对整体同步任务的影响。大表可结合 GROUP 分组并行装载,提高效率并降低故障重装成本。
无主键表的核心风险在于 UPDATE/DELETE 缺少天然唯一定位依据,可能导致执行效率下降甚至数据定位异常,建议重点排查并单独分组同步或使用 ROWID 映射。
此外,在正式生产库上统计超大表行数时,COUNT(*) 一类精确统计可能产生明显 I/O,建议避开业务高峰,优先使用达梦官方的 TABLE_ROWCOUNT 函数进行同步前盘点。
更多推荐
所有评论(0)