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 中不再成立,我们可以按工作负载而不是按数据副本来划分计算资源。

云服务层 Cloud Services 元数据管理 · 查询解析与优化 · 事务 · 访问控制 · 安全认证 (“大脑”:不存业务数据,只存对象定义与状态) 计算层:虚拟仓库(按工作负载隔离) WH_ETL X-Small · 加载/转换 自动挂起 60s WH_BI Medium · 报表查询 多集群 1–3 WH_DS Large · 数据科学 按需启动 存储层:云对象存储(列式压缩 · 单一数据副本) SALES_DB PUBLIC / STG HR_DB PUBLIC / RAW DW_DB DIM / FACT STAGE_AREA 临时/落地区 多个虚拟仓库共享同一份存储数据,互不阻塞;计算按需伸缩,存储按实际用量计费

二、核心对象层级:从数据库到表

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,并显式指定执行它的虚拟仓库。

迁移初期建议保留源平台的命名习惯,不要急于“美化”对象名。等数据比对通过、业务验证完成后,再统一做命名规范化,可以显著降低排障难度。

五、迁移前必须确认的映射检查项

在正式执行迁移脚本前,建议逐项确认以下内容,避免后期返工:

  1. 数据类型映射:Oracle 的 NUMBER(38,0) 对应 Snowflake 的 NUMBER(38,0);VARCHAR2(200) 对应 VARCHAR(200);DATE 在 Oracle 含时分秒,Snowflake 的 DATE 只含日期,需改用 TIMESTAMP_NTZ。
  2. 大小写敏感:Snowflake 默认对象名大写,源平台若使用小写或混合大小写,需统一加双引号或全部转大写。
  3. 约束与索引:Snowflake 支持主键、外键声明但不强制,也不支持传统索引;源平台的索引应转换为聚簇键(Cluster Key)或直接省略。
  4. 存储过程语法:PL/SQL 的游标、异常处理需改写为 Snowflake Scripting 或 JavaScript 存储过程。
  5. 调度依赖:源平台的 Job 链需转换为 Task 的 AFTER 依赖关系,形成 DAG。

把这张映射表建立起来并逐项验证,Snowflake 迁移就从“凭感觉改 SQL”变成了“按规则做转换”,后续的加载、比对、切换才有稳定的基础。