3. Snowflake架构与核心对象映射
把源平台的数据资产迁移到 Snowflake,第一步不是写 SQL,而是建立一张“对象映射表”:源平台里的每一个库、模式、表、视图、存储过程、调度任务,究竟对应 Snowflake 中的哪个对象。映射错了,后面所有迁移脚本都会返工。要建立正确的映射规则,必须先理解 Snowflake 的架构特点——它与传统数据库最大的区别在于存储与计算分离,以及由此衍生出的多集群共享数据架构。
一、多集群共享数据架构:理解 Snowflake 的底层逻辑
在传统 MPP 数据库(如 Teradata、Greenplum、Oracle RAC)中,存储和计算是耦合的:数据分布在各个节点本地磁盘上,扩容意味着重分布数据。Snowflake 则把两者彻底拆开:
- 存储层(Storage Layer):数据以列式压缩格式存放在云对象存储(S3/Azure Blob/GCS)中,由 Snowflake 统一管理,用户看不到文件,只看到“表”。
- 计算层(Compute Layer):由一组组虚拟仓库(Virtual Warehouse)组成,每个虚拟仓库是一组可弹性伸缩的云算力节点,负责执行查询、加载、转换。
- 云服务层(Cloud Services Layer):负责元数据管理、查询解析优化、事务、访问控制、安全认证等,是“大脑”。
这种架构带来一个关键结论:多个虚拟仓库可以同时读取同一份存储层数据,互不争抢、互不阻塞。这就是“多集群共享数据”的含义。对迁移而言,它意味着源平台中“一个库只能被一个实例访问”的约束在 Snowflake 中不再成立,我们可以按工作负载而不是按数据副本来划分计算资源。
二、核心对象层级:从数据库到表
Snowflake 的对象层级非常清晰,迁移时按这个层级逐级映射即可:
| 层级 | Snowflake 对象 | 作用 | 典型源平台对应 |
|---|---|---|---|
| 1 | 数据库 Database | 对象的最外层容器 | Oracle 实例 / SQL Server 数据库 |
| 2 | 模式 Schema | 数据库内的命名空间 | Oracle Schema / PostgreSQL Schema |
| 3 | 表 Table | 存储结构化数据 | 各平台物理表 |
| 4 | 视图 View | 逻辑查询封装 | 普通视图 |
| 5 | 物化视图 Materialized View | 预计算结果,自动刷新 | Oracle 物化视图 |
| 6 | 存储过程 Procedure | 过程化逻辑(SQL/JS/Python) | PL/SQL / T-SQL 存储过程 |
| 7 | 任务 Task | 定时/依赖调度 | Oracle Job / SQL Agent Job |
| 8 | 流 Stream | 捕获表变更(CDC) | Oracle CDC / 触发器 |
需要特别注意的是,Snowflake 中没有“实例”概念,一个账户下可以有多个数据库,数据库之间通过全限定名 数据库.模式.对象 访问。迁移时,源平台的“实例名”通常映射为 Snowflake 的数据库名,源平台的“Schema”直接映射为 Snowflake 的 Schema,源平台的“表”映射为 Snowflake 的表。
三、虚拟仓库:迁移中最容易被忽视的映射对象
很多迁移项目只关注表结构,却忽略了源平台的“计算资源”也需要映射。在 Oracle 中,计算资源是隐式的(由实例承担);在 Snowflake 中,计算资源是显式的虚拟仓库。映射原则是按工作负载拆分,而不是按源库拆分:
- 加载仓库:负责 COPY INTO、Snowpipe 等数据加载,建议 X-Small 或 Small,设置自动挂起 60 秒。
- 转换仓库:负责 ETL/ELT 中的大表 JOIN、聚合,建议 Medium 或 Large,按任务时长启动。
- 查询仓库:负责 BI 报表、即席查询,建议 Medium,开启多集群(1–3)应对并发高峰。
- 数据科学仓库:负责特征工程、模型训练,建议 Large 或 X-Large,按需启动、用完即停。
这样做的直接收益是:BI 报表的慢查询不会拖垮 ETL 加载,数据科学的大内存计算也不会挤占报表资源。源平台中“一个实例扛所有负载”的模式,在 Snowflake 中应被彻底重构。
四、映射规则示例:从 Oracle 到 Snowflake
下面给出一份可直接参考的映射规则示例(示例参数为教学假设,实际项目需按真实对象清单调整):
-- 源平台(Oracle)
-- 实例: ORCL
-- Schema: SALES
-- 表: SALES.ORDERS
-- 视图: SALES.V_ORDER_SUMMARY
-- 存储过程: SALES.P_LOAD_ORDERS
-- 调度: DBMS_SCHEDULER JOB 'JOB_LOAD_ORDERS' 每天 02:00
-- 映射到 Snowflake
CREATE DATABASE ORCL_SALES; -- 实例+Schema 合并为数据库
CREATE SCHEMA ORCL_SALES.PUBLIC; -- 保留原 Schema 语义
CREATE TABLE ORCL_SALES.PUBLIC.ORDERS ( -- 表名保持一致,便于溯源
ORDER_ID NUMBER(38,0) NOT NULL,
CUSTOMER_ID NUMBER(38,0),
ORDER_DATE DATE,
AMOUNT NUMBER(18,2),
STATUS VARCHAR(20)
);
CREATE VIEW ORCL_SALES.PUBLIC.V_ORDER_SUMMARY AS
SELECT CUSTOMER_ID, SUM(AMOUNT) AS TOTAL_AMT
FROM ORCL_SALES.PUBLIC.ORDERS
GROUP BY CUSTOMER_ID;
CREATE PROCEDURE ORCL_SALES.PUBLIC.P_LOAD_ORDERS()
RETURNS VARCHAR
LANGUAGE SQL
AS
BEGIN
COPY INTO ORCL_SALES.PUBLIC.ORDERS
FROM @ORCL_SALES.PUBLIC.STG_ORDERS
FILE_FORMAT = (TYPE = CSV SKIP_HEADER = 1);
RETURN 'loaded';
END;
CREATE TASK ORCL_SALES.PUBLIC.TASK_LOAD_ORDERS
WAREHOUSE = WH_ETL
SCHEDULE = 'USING CRON 0 2 * * * UTC'
AS
CALL ORCL_SALES.PUBLIC.P_LOAD_ORDERS();
这段示例体现了三条关键映射规则:第一,源平台的“实例+Schema”在 Snowflake 中通常合并为“数据库+Schema”,用数据库名保留源实例标识;第二,表名、列名尽量保持原样,便于迁移后做数据比对和问题溯源;第三,源平台的调度 Job 映射为 Snowflake Task,并显式指定执行它的虚拟仓库。
五、迁移前必须确认的映射检查项
在正式执行迁移脚本前,建议逐项确认以下内容,避免后期返工:
- 数据类型映射:Oracle 的
NUMBER(38,0)对应 Snowflake 的NUMBER(38,0);VARCHAR2(200)对应VARCHAR(200);DATE在 Oracle 含时分秒,Snowflake 的DATE只含日期,需改用TIMESTAMP_NTZ。 - 大小写敏感:Snowflake 默认对象名大写,源平台若使用小写或混合大小写,需统一加双引号或全部转大写。
- 约束与索引:Snowflake 支持主键、外键声明但不强制,也不支持传统索引;源平台的索引应转换为聚簇键(Cluster Key)或直接省略。
- 存储过程语法:PL/SQL 的游标、异常处理需改写为 Snowflake Scripting 或 JavaScript 存储过程。
- 调度依赖:源平台的 Job 链需转换为 Task 的
AFTER依赖关系,形成 DAG。
把这张映射表建立起来并逐项验证,Snowflake 迁移就从“凭感觉改 SQL”变成了“按规则做转换”,后续的加载、比对、切换才有稳定的基础。