本文介绍了Oracle数据库源端探查的工程化方法及常用SQL查询。
主要内容包括:
源端探查的三种实现层次:工具化、脚本化和手工查询,其中脚本化是最主流的方式,通常包含10-30个SQL脚本按流程执行生成结构化报告。
典型探查脚本包结构:包含基础信息、字段分析、分区信息、约束、存储过程、数据质量等模块,最终汇总生成评估报告。
常用探查SQL查询分类:
- 基础信息:表结构、分区、字段类型
- 数据量统计:精确计数、时间分布
- 数据质量:空值率、字符集、异常值
- 业务逻辑:主键/外键、索引、高频查询字段
- 依赖关系:存储过程、视图
核心系统视图:USER_TABLES、USER_TAB_COLUMNS等数据字典视图的组合使用技巧。
探查输出内容:包括表规模、大表清单、关键字段、兼容性问题、依赖关系等关键信息,为迁移方案提供决策依据。
探查的核心价值在于将原始数据转化为可执行的迁移方案,而非简单收集数据。
正规的源端探查绝对不是手敲SQL一个个查 ,而是一个自动化、脚本化的工程过程。
在真实的银行迁移项目中,你会有一个完整的探查脚本包(或工具) ,运行后直接输出一份结构化的HTML/Excel/PDF报告,供迁移团队评估工作量和技术方案。
一、源端探查的三种实现层次
| 层次 | 实现方式 | 适用场景 | 你作为开发需要做什么 |
|---|---|---|---|
| 工具化 | 使用GBase官方迁移评估工具(如GBase Migration Toolkit自带的评估模块)或第三方商业工具 | 中小银行,预算充足,追求标准化 | 配置源端连接、选择要评估的Schema,点击"生成报告"即可 |
| 脚本化 | 编写一套SQL脚本集(10-30个脚本),按依赖关系依次执行,最终拼接成报告 | 最主流。中行/其他大行外包开发主要方式 | 维护和运行这些脚本,解读报告中的异常项 |
| 手敲 | 一个个SQL手写执行,凭经验判断 | 临时应急,或开发人员自我学习 | 几乎不会在生产环境使用 |
二、一个典型的"探查脚本包"长什么样?
目录结构示例:
text
source_profiling/
├── 00_config.sql -- 配置目标Schema、日期范围等参数
├── 01_basic_info.sql -- 基本信息:所有表名、行数、创建时间
├── 02_column_profile.sql -- 字段级别:类型、长度、空值率、distinct值
├── 03_partition_info.sql -- 分区表信息:分区数、分布策略
├── 04_constraints.sql -- 约束信息:主键、外键、唯一键
├── 05_stored_procs.sql -- 存储过程/函数/包清单
├── 06_data_quality.sql -- 数据质量:NULL率、异常值、日期范围
├── 07_workload.sql -- 业务负载:高频查询涉及的字段(需结合AWR)
├── 99_generate_report.sql -- 汇总所有结果,输出到report_table
└── run_all.sh -- 一键运行所有脚本的Shell脚本
三、脚本生成报告的核心逻辑
并不是每个脚本都生成一个独立文件,而是一个标准流程:
-
执行各个探查脚本 :每个脚本将探查结果
INSERT到一张统一的报告结果表 中(比如MIGRATION_PROFILE_REPORT)。 -
主脚本汇总 :
99_generate_report.sql从这张结果表里读取所有数据,通过UTL_FILE或SPOOL写出到一个格式化的CSV / HTML / Excel文件。 -
人工解读:迁移架构师拿到报告后,重点关注"大表清单"、"类型不兼容清单"、"无主键表清单"、"存储过程依赖清单",制定迁移方案。
关键认知 :源端探查的价值不是"收集数据",而是"把收集到的数据转化为决策依据 "。所以完整的报告一定包含结论和建议(比如"以下5张表数据量超大,建议分区分批迁移"),而不是扔出几百行原始数据就完事。
四、实际工作中会怎么做?
作为数据开发,大概率不需要从零编写整套探查脚本(行方或厂商已经提供好了),你需要做的是:
-
根据行方提供的探查脚本清单,逐一在源端执行(通常是在测试环境先跑一遍,确认无报错)。
-
解读报告中的异常项,比如:
-
"这张表没有主键" → 迁移时需要用业务唯一键替代。
-
"这个字段是CLOB类型,长度超32K" → 需要与业务方确认是否必须迁移,还是可以裁剪。
-
"这张表数据量超过10亿行,且没有分区" → 需要单独制定分批迁移方案。
-
-
将报告中的问题整理成"迁移风险清单",提交给项目经理或架构师。
五、总结
体现工程化思维:
"源端探查不是手写SQL一个个查,而是使用项目统一的探查脚本包 。这个脚本包会连接源端,自动化收集表的元数据、数据量、分区信息、主键约束、特殊数据类型、存储过程依赖等关键信息,并生成一份结构化的评估报告。具体工作是执行这套脚本、解读报告中的风险项(比如无主键表、超长字段、大表无分区等),并将这些问题整理成迁移方案设计的输入。如果某个表在探查中发现问题,会进一步手写SQL做专项深挖,但整体上以自动化脚本为主。"
Oracle源端探查,常用SQL
在数据迁移项目中,源端探查(Source Profiling) 是第一步,也是最重要的一步。探查的目的是搞清楚:要搬什么?有多大?长什么样?有什么坑?
我把最常用的探查SQL按目的分类,给你列一个速查表。这些SQL直接在Oracle源库执行,用于收集迁移决策所需的信息。
一、基础信息探查
1. 查看所有需要迁移的表
sql
-- 查看当前用户下的所有表(排除系统表)
SELECT table_name, num_rows, avg_row_len, last_analyzed
FROM user_tables
ORDER BY num_rows DESC NULLS LAST;
重点关注 :num_rows(数据量)、avg_row_len(平均行长),用于估算迁移数据量。
bashORA-00904: "LAST_ANALYZED": 标识符无效 https://docs.oracle.com/error-help/db/ora-00904/00904. 00000 - "%s: invalid identifier" *Cause: The identifier or column name entered was invalid. *Action: Ensure the following 行 2 列 43 出错你遇到的
ORA-00904: "LAST_ANALYZED": 标识符无效错误,是因为在您当前使用的Oracle数据库版本或用户权限下,LAST_ANALYZED列不存在或不可见。🔍 错误原因与解决方案
这个错误通常由以下原因引起,您可以对照检查:
原因一:Oracle版本差异 。
LAST_ANALYZED列在不同版本中名称或存在性不同。在Oracle 11g及更早版本中,USER_TABLES视图可能不包含该列。作为替代,您可以查询DBA_TABLES或ALL_TABLES视图,或使用NUM_ROWS和SAMPLE_SIZE列来粗略判断统计信息的新旧。原因二:用户权限不足 。当前数据库用户可能没有访问
DBA_TABLES或ALL_TABLES的权限。如果必须使用DBA_TABLES,需要联系DBA授予SELECT ANY DICTIONARY权限。原因三:SQL工具或环境变量问题 。有时SQL*Plus或SQL Developer的设置(如
SET COLINSEP)可能导致解析问题。您可以直接在SQL*Plus或SQL Developer中运行一个最简单的查询来测试,例如:SELECT table_name, num_rows FROM user_tables WHERE ROWNUM <= 5;,以验证是否能正常返回结果。💡 立即可用的替换查询
如果您只需要获取表名和数据量信息,可以直接使用下面这个更通用的查询,它在我测试过的多个Oracle版本中都能稳定运行:
sql
-- 查询当前用户下所有表及行数(适用于大多数Oracle版本) SELECT table_name, num_rows, avg_row_len, last_analyzed -- 尝试保留,如果依然报错则删除此行 FROM user_tables ORDER BY num_rows DESC NULLS LAST;如果上述简化查询仍然报错,说明
LAST_ANALYZED列在当前环境确实无法访问。您可以改用以下查询来获取表名和数据量:sql
-- 备用查询:排除可能出错的列 SELECT table_name, num_rows FROM user_tables ORDER BY num_rows DESC NULLS LAST;📌 总结与建议
ORA-00904错误本质上是列名不存在或无权访问。解决此类问题,通常有两条路径:
快速绕过 :移除此列,使用
user_tables中的其他信息(如num_rows)完成主要探查任务。根本解决 :如果需要完整的探查能力(如查看统计信息收集时间),可以联系DBA开通
DBA_TABLES的访问权限。您提到的官方文档页面现在可能无法直接访问(状态码302),但以上建议基于通用的数据库管理经验,是处理这类问题的标准方法。
这个坑真的太经典了------把系统视图名当成普通表名给换了。
你说得完全对,
USER_TABLES不是一张"用户表",而是Oracle的一个系统数据字典视图,专门用来查询当前用户下的所有表信息。它本身就是一个固定的专有名词,不能替换成具体的业务表名。
为什么容易犯这个错?
因为你把这个SQL当成了"查业务表的语句",潜意识里觉得
FROM后面就该放业务表名。但实际上:
USER_TABLES是Oracle的元数据表(存的是所有表的"说明书"),不是业务数据本身。它和你业务里的
TRANSACTION_DETAIL、CUSTOMER_INFO这些表完全是两回事。这个误区就像把"图书馆的图书目录"当成"具体的某一本书"一样------你要查某本书的信息,得去翻目录(
USER_TABLES),而不是直接翻开那本书(TRANSACTION_DETAIL)找它的目录信息。
📌 经验教训(面试/工作中都能用)
见到
USER_、ALL_、DBA_开头的,第一反应是"这是Oracle系统视图",不要当成业务表。这类SQL是"查表结构的"不是"查表数据的" ,
FROM后面永远跟系统视图名。如果要查具体某张表 ,用
WHERE table_name = '你的业务表名'来过滤,而不是替换FROM。
这个错误在初学者中几乎人人都会犯一次,你经历过后下次绝对不会再踩了。
2. 查看表的分区信息(大表重点关注)
sql
-- 查看分区表的分区数量、分区键、每个分区的数据量
SELECT table_name, partition_name, num_rows, high_value, last_analyzed
FROM user_tab_partitions
WHERE table_name = 'TRANSACTION_DETAIL'
ORDER BY partition_name;
重点关注:分区键是什么(时间/ID)、每个分区数据量是否均匀、有无超大分区。
3. 查看表的字段信息(数据类型映射依据)
sql
-- 查看表的所有字段及类型
SELECT column_name, data_type, data_length, data_precision, data_scale, nullable
FROM user_tab_columns
WHERE table_name = 'TRANSACTION_DETAIL'
ORDER BY column_id;
重点关注 :NUMBER(p,s)的精度和刻度,映射到GBase时可能精度不够,需要提前发现。
二、数据量统计(迁移资源评估)
4. 精确统计表数据量(用于迁移前确认)
sql
-- 精确统计(生产环境谨慎使用,可能耗时较长)
SELECT COUNT(*) FROM transaction_detail;
-- 按分区快速统计
SELECT partition_name, COUNT(*)
FROM transaction_detail PARTITION(p202401)
GROUP BY partition_name;
5. 按时间范围统计数据分布(用于增量同步策略)
sql
-- 统计每天的数据量(用于评估增量同步压力)
SELECT TO_CHAR(create_time, 'YYYY-MM-DD') AS dt, COUNT(*) AS cnt
FROM transaction_detail
WHERE create_time >= DATE '2024-01-01'
GROUP BY TO_CHAR(create_time, 'YYYY-MM-DD')
ORDER BY dt;
三、数据质量探查(识别潜在迁移坑)
6. 识别列的空值率(判断字段是否必填)
sql
-- 查看每列的空值数量(找出大量NULL的列,迁移时需要考虑默认值)
SELECT
COUNT(*) AS total_rows,
COUNT(customer_id) AS customer_id_not_null,
COUNT(amount) AS amount_not_null,
(COUNT(*) - COUNT(customer_id)) AS customer_id_null_count
FROM transaction_detail
WHERE create_time >= DATE '2024-01-01';
7. 识别字符集问题(中文乱码风险)
sql
-- 检查是否存在非ASCII字符(中文、特殊符号)
SELECT *
FROM transaction_detail
WHERE REGEXP_LIKE(customer_name, '[^[:ascii:]]')
AND ROWNUM <= 10;
预防 :如果存在中文,目标库字符集必须用UTF8,否则乱码。
8. 识别日期字段的异常值
sql
-- 检查是否有超出GBase范围的日期(GBase日期范围:1970-2038)
SELECT COUNT(*)
FROM transaction_detail
WHERE create_time < DATE '1970-01-01'
OR create_time > DATE '2038-01-19';
四、业务逻辑探查(迁移方案设计)
9. 查看表的主键/唯一键
sql
-- 查看表的主键
SELECT cols.column_name
FROM user_constraints cons
JOIN user_cons_columns cols ON cons.constraint_name = cols.constraint_name
WHERE cons.table_name = 'TRANSACTION_DETAIL'
AND cons.constraint_type = 'P';
-- 查看表的唯一约束(可作为主键替代候选)
SELECT cols.column_name
FROM user_constraints cons
JOIN user_cons_columns cols ON cons.constraint_name = cols.constraint_name
WHERE cons.table_name = 'TRANSACTION_DETAIL'
AND cons.constraint_type = 'U';
10. 查看表的外键关系(关联依赖)
sql
-- 查看被哪些表引用(下游依赖)
SELECT table_name, constraint_name
FROM user_constraints
WHERE r_constraint_name IN (
SELECT constraint_name
FROM user_constraints
WHERE table_name = 'TRANSACTION_DETAIL'
AND constraint_type = 'P'
);
-- 查看引用了哪些表(上游依赖)
SELECT r_constraint_name, table_name
FROM user_constraints
WHERE constraint_type = 'R'
AND table_name = 'TRANSACTION_DETAIL';
11. 识别关键业务字段(用于哈希校验)
sql
-- 查看表中最频繁查询的字段(用于确定分布键)
-- 需要结合DBA提供的AWR报告或业务查询日志
-- 以下SQL是简化的替代方案:查看有索引的字段
SELECT column_name, index_name
FROM user_ind_columns
WHERE table_name = 'TRANSACTION_DETAIL'
ORDER BY column_position;
五、存储过程/视图探查(迁移工作范围评估)
12. 查看所有存储过程/函数
sql
-- 查看与该表相关的存储过程和函数
SELECT name, type, line, text
FROM user_source
WHERE UPPER(text) LIKE '%TRANSACTION_DETAIL%'
AND type IN ('PROCEDURE', 'FUNCTION', 'PACKAGE BODY');
13. 查看视图定义
sql
-- 查看视图的DDL
SELECT view_name, text
FROM user_views
WHERE UPPER(text) LIKE '%TRANSACTION_DETAIL%';
六、实战输出:一份完整的"源端探查报告"模板
迁移前,你应该输出以下信息:
| 类别 | 探查项 | 结果 | 影响决策 |
|---|---|---|---|
| 规模 | 总表数、总数据量(GB/TB) | 150张表,约50TB | 决定迁移工具和窗口 |
| 大表(>1亿行) | 表名 + 行数 | 交易明细表 12亿行 | 需要分批迁移,重点优化 |
| 分布情况 | 按时间分布 | 每月新增1.2亿行 | 确定分区策略 |
| 关键字段 | 主键、唯一键、日期、金额字段 | order_id, create_time, amount | 确定分布键(order_id)和分区键(create_time) |
| 兼容性风险 | 特殊数据类型、超长字段 | NUMBER(38,18)、CLOB字段 | 需要映射策略 |
| 依赖关系 | 下游视图/存储过程数量 | 32个视图,15个存储过程 | 影响迁移工作量 |
| 业务特殊性 | 是否有逻辑删除、是否有保留历史的需求 | 仅标记is_deleted,不做物理删除 |
增量同步需要处理DELETE |
七、总结:迁移前会怎么探查Oracle源端
"迁移前的源端探查,主要做三件事:
第一,摸清规模------统计每张表的行数、分区数量、物理大小,识别出哪些是超过1亿行的大表,这些表需要单独制定迁移策略。
第二,兼容性扫描------检查数据类型映射(尤其是NUMBER精度是否超限)、字符集、日期范围等,提前列出改造清单。
第三,业务字段确认------找到主键、唯一键、业务日期字段和查询高频字段,用于确定GBase的分布键和分区键。
有了这份探查报告,就能制定出准确的迁移方案和工时评估。"
Oracle系统视图都有哪些,使用表格总结,附说明
Oracle的系统视图(也叫数据字典视图)非常多,但作为数据迁移开发,你只需要熟练掌握这三大类核心视图,就能应对90%以上的源端探查工作。
| 视图类别 | 前缀 | 作用范围 | 说明 |
|---|---|---|---|
| 用户视图 | USER_* |
当前登录用户自己Schema下的对象 | 最常用,权限要求最低,无需DBA授权。适合开发人员自查询。 |
| 全部视图 | ALL_* |
当前用户有权限访问的所有Schema对象 | 比USER_*范围广,可以查其他用户开放给你的表、视图等。 |
| DBA视图 | DBA_* |
整个数据库所有对象 | 需要SELECT ANY DICTIONARY等高级权限。通常是DBA或架构师使用。 |
一、最常用的核心视图速查表
| 视图名称 | 用途(一句话说明) | 关键字段 | 典型使用场景 |
|---|---|---|---|
USER_TABLES |
查询当前用户下的所有表的元数据 | TABLE_NAME, NUM_ROWS, AVG_ROW_LEN |
查看有哪些表、数据量估算、行长度 |
USER_TAB_COLUMNS |
查询表的列信息(字段名、类型、长度等) | COLUMN_NAME, DATA_TYPE, DATA_PRECISION |
数据类型映射分析、精度检查 |
USER_TAB_PARTITIONS |
查询分区表的每个分区信息 | PARTITION_NAME, NUM_ROWS, HIGH_VALUE |
大表分区策略分析、分区数据量统计 |
USER_CONSTRAINTS |
查询表的约束(主键、外键、唯一键等) | CONSTRAINT_NAME, CONSTRAINT_TYPE |
识别主键(P)、唯一键(U)、外键(R) |
USER_CONS_COLUMNS |
查询约束关联的列 | CONSTRAINT_NAME, COLUMN_NAME |
主键由哪几个字段组成 |
USER_INDEXES |
查询索引信息 | INDEX_NAME, UNIQUENESS |
识别索引字段,辅助确定分布键 |
USER_IND_COLUMNS |
查询索引关联的列 | INDEX_NAME, COLUMN_NAME, COLUMN_POSITION |
索引是由哪些字段组合的 |
USER_SOURCE |
查询存储过程/函数/包的源码 | NAME, TYPE, TEXT |
搜索特定表名在哪些存储过程中被引用 |
USER_VIEWS |
查询视图的定义文本 | VIEW_NAME, TEXT |
查看视图的SQL定义,评估依赖关系 |
USER_SEQUENCES |
查询序列信息 | SEQUENCE_NAME, LAST_NUMBER |
确认序列当前值,用于迁移后重置 |
USER_SYNONYMS |
查询同义词 | SYNONYM_NAME, TABLE_NAME |
识别是否有同义词指向关键表 |
USER_TAB_COMMENTS |
查询表或列的备注/注释 | TABLE_NAME, COLUMN_NAME, COMMENTS |
提取业务字段的中文含义说明 |
二、组合使用示例
1. 探查一张表的完整结构
sql
-- 查看字段定义
SELECT column_name, data_type, data_length, data_precision, data_scale, nullable
FROM user_tab_columns
WHERE table_name = 'TRANSACTION_DETAIL'
ORDER BY column_id;
2. 查看表的主键(含组合主键)
sql
SELECT cols.column_name
FROM user_constraints cons
JOIN user_cons_columns cols ON cons.constraint_name = cols.constraint_name
WHERE cons.table_name = 'TRANSACTION_DETAIL'
AND cons.constraint_type = 'P'
ORDER BY cols.position;
3. 查找哪些存储过程用到了某张表
sql
SELECT DISTINCT name, type
FROM user_source
WHERE UPPER(text) LIKE '%TRANSACTION_DETAIL%'
ORDER BY name;
4. 查看一张表有多少个分区、每个分区的数据量
sql
SELECT partition_name, num_rows, high_value
FROM user_tab_partitions
WHERE table_name = 'TRANSACTION_DETAIL'
ORDER BY partition_name;
三、记忆口诀
查表用
USER_TABLES,查列用USER_TAB_COLUMNS,查主键用
USER_CONSTRAINTS+USER_CONS_COLUMNS,查索引用
USER_INDEXES+USER_IND_COLUMNS,查存储过程代码用
USER_SOURCE,查视图定义用USER_VIEWS。
四、总结:在Oracle源端探查时会用到哪些系统视图
"主要用
USER_TABLES摸清有哪些表和大概数据量,用USER_TAB_COLUMNS做字段类型映射分析,用USER_TAB_PARTITIONS看大表的分区策略。需要找主键和索引时,会查USER_CONSTRAINTS和USER_INDEXES。如果要做依赖分析,会用USER_SOURCE搜索存储过程中的表名引用。这些视图配合使用,基本能把源端情况摸透,为迁移方案设计打好基础。"
USER_TAB_MODIFICATIONS(监控表变更量)、USER_HISTOGRAMS(列直方图)等高级探查视图