接着上一篇文章:迁移Oracle HR 示例 schema 到 PostgreSQL中,本文做Oracle SH(Sales History)示例 schema的迁移,SH schema比HR schema更大更复杂,本次迁移的重点是:

  • 分区表
  • 外部数据加载

使用的是Oracle 19c的示例 schema,下载命令如下:

git clone --depth 1 --branch v19c https://github.com/oracle-samples/db-sample-schemas.git

SH schema的安装脚本为sales_history/sh_main.sql,其主要构成按序为(以下省略.sql后缀):

  1. csh_v3:创建表
  2. lsh_v3:加载数据到表
  3. psh_v3:加载后的操作

我们也按以上顺序来迁移。依次形成了以下脚本:

  • csh_v3.sql:创建表
  • lsh_v3.sql:加载数据
  • cons_v3.sql:创建约束
  • idx_v3.sql:创建索引
  • views_v3.sql:创建视图,物化视图
  • cmnts_v3.sql:创建注释

csh_v3:创建表

这部分比较容易,分区的语法对应上就好,另外建立约束的部分放在数据加载后来做。

还有PG并没有Oracle的OLTP表压缩功能。

Oracle的分区语法丰富,普适性较强。例如范围分区支持VALUES LESS THAN。PG只支持FOR VALUES FROM … TO。不过问题不大。

看一个sales表的示例。

Oracle语法:

CREATE TABLE sales (prod_id             NUMBER          NOT NULL,cust_id             NUMBER          NOT NULL,time_id             DATE            NOT NULL,channel_id          NUMBER          NOT NULL,promo_id            NUMBER          NOT NULL,quantity_sold       NUMBER(10,2)    NOT NULL,amount_sold         NUMBER(10,2)    NOT NULL)PARTITION BY RANGE (time_id)( partition sales_1995 VALUES LESS THAN(TO_DATE('1996-01-01 00:00:00','SYYYY-MM-DD HH24:MI:SS','NLS_CALENDAR=GREGORIAN')) COMPRESS,partition sales_1996 VALUES LESS THAN(TO_DATE('1997-01-01 00:00:00','SYYYY-MM-DD HH24:MI:SS','NLS_CALENDAR=GREGORIAN')) COMPRESS,
...

PostgreSQL的语法:

CREATE TABLE sales (prod_id             NUMERIC                 NOT NULL,cust_id             NUMERIC                 NOT NULL,time_id             DATE            NOT NULL,channel_id          NUMERIC         NOT NULL,promo_id            NUMERIC                 NOT NULL,quantity_sold       NUMERIC(10,2)   NOT NULL,amount_sold         NUMERIC(10,2)   NOT NULL)PARTITION BY RANGE (time_id);CREATE TABLE sales_1995 PARTITION OF salesFOR VALUES FROM (MINVALUE) TO ('1996-01-01');CREATE TABLE sales_1996 PARTITION OF salesFOR VALUES FROM ('1996-01-01') TO ('1997-01-01');...

lsh_v3:加载数据到表

这部分消耗时间最多,主要在数据文件的格式转换。Oracle是用SQL Loader,PostgreSQL则用COPY。

💡 先厘清一个概念。对于DATE数据类型,PG的精度是到天,而Oracle的精度是到秒。

本部分处理的主要问题:

  • 1:Oracle示例表中用DATE定义的列,实际只需要到天就可以了,但数据文件中的值却是1998-12-27-00-00-00,而非1998-12-27。所以我们需要去掉尾部的00-00-00
  • 2:多余的分隔符。按说3个字段只需要2个分隔符,但Oracle也支持尾部再多放一个分隔符。而PG不认,我们只需要去掉行末的分隔符即可。
  • 3:数据文件的字段比表的字段多
  • 4:建立外部表

问题1的处理较简单,例如对于times表:

\copy times from program 'sed "s/-00-00-00//g" time_v3.dat'WITH (FORMAT csv,DELIMITER '|'
);

用元命令而非SQL命令的原因在于要使用相对路径。

问题2的处理也是用sed,例如对于countries表:

\copy countries from program 'sed "s/|$//g" coun_v3.dat'WITH (FORMAT csv,DELIMITER '|'
);

有些表同时出现了问题1和2,例如customers表和products表:

\copy customers from program 'sed "s/-00-00-00//g;s/|$//g" cust1v3.dat'WITH (FORMAT csv,DELIMITER '|'
);

问题3的处理稍微不同,出于性能考虑,预处理生成了中间文件,而非之前的即时处理。例如对于sales表,他只有7个字段,而数据文件有9个字段。

即时处理如下,但结果1小时后也没出来,所以放弃了:

\copy sales from program 'sed "s/-*[0-9]\+\(\.[0-9]\+\)\?|$//g"|sed "s/|-*[0-9]\+\(\.[0-9]\+\)\?|$//g" sale1v3.dat'WITH (FORMAT csv,DELIMITER '|'
);

预处理方式如下:

sampledb=> \timing
Timing is on.sampledb=> \! time sed "s/-*[0-9]\+\(\.[0-9]\+\)\?|$//g" sale1v3.dat > 1real    0m34.503s
user    0m33.504s
sys     0m0.271s
sampledb=> \! time sed "s/|-*[0-9]\+\(\.[0-9]\+\)\?|$//g" 1 > 2real    0m19.119s
user    0m18.517s
sys     0m0.226s
sampledb=> \! mv 2 sale1v3_pg.dat
sampledb=> \copy sales from sale1v3_pg.datWITH (FORMAT csv,DELIMITER '|'
);
COPY 916039
Time: 9422.693 ms (00:09.423)

可以看到,预处理用了近54秒,导入用了9秒。

问题4的例子是costs表。他其实用到了之前9个字段的数据文件。

外部表的建立用了file_fdw扩展,这是PG原生的扩展,详见这里。

CREATE FOREIGN TABLE sales_transactions_ext
( PROD_ID               NUMERIC,CUST_ID               NUMERIC,TIME_ID               DATE,CHANNEL_ID    NUMERIC,PROMO_ID              NUMERIC,QUANTITY_SOLD   NUMERIC,AMOUNT_SOLD   NUMERIC(10,2),UNIT_COST     NUMERIC(10,2),UNIT_PRICE    NUMERIC(10,2)
) SERVER file_server
OPTIONS
(
format 'csv', filename 'sale1v3_fdw.dat', delimiter '|'
);

需要特别说明,我用的是相对路径,因此需要把数据文件拷贝到PG服务器可访问的目录,如$PGDATA。不过还是建议用绝对路径。

psh_v3:加载后的操作

我没有psh_v3.sql,而是用idx_v3.sql,views_v3.sql和cmnts_v3.sql对应。

最后

所有的脚本都在Github上了,下一篇我们迁Customer Orders 示例 schema。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/88328.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/88328.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/88328.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1.1 ARMv8/ARMv9安全扩展

目录1.1.1 ARM架构安全演进1.1.2 ARMv8安全特性异常级别(EL)安全模型关键安全扩展1.1.3 ARMv9安全创新机密计算架构(CCA)增强的隔离机制1.1.4 安全扩展的TF-A支持1.1.5 安全扩展配置示例1.1.1 ARM架构安全演进 ARM架构从v7到v9的安全演进路线: ARMv7:引…

更新用户隐私协议后还是 ail api scope is not declared in the privacy agreement怎么办??!

saveImageToPhotosAlbum:fail api scope is not declared in the privacy agreement昨天明明可以了,开了个会出来,又不行了,真要命啊啊啊啊啊啊啊啊啊啊(现在回想起来可能是因为我把发布的那个版本删了,因为那个只是用来测试用的e…

练习:对象数组 5

定义一个长度为 3 的数组,数组存储 1~3 名学生对象作为初始数据,学生对象的学号,姓名各不相同。学生的属性:学号,姓名,年龄。要求 1:再次添加一个学生对象,并在添加的时候进行学号的…

Linux 中的 .bashrc 是什么?配置详解

如果你使用过 Linux 终端,那么你很可能接触过 .bashrc 文件。这个功能强大的脚本是个性化命令行环境并使其更高效运行的关键。 在本文中,我们将向你介绍这个文件是什么,在哪里可以找到它,以及如何安全地编辑它。你还将学到一些实…

JVM运行时数据区深度解析

💾 JVM运行时数据区深度解析 文章目录💾 JVM运行时数据区深度解析🎯 引言📚 方法区📋 方法区存储内容🔄 从永久代到元空间的演进永久代时期(JDK 8之前)元空间时期(JDK 8及…

.NET nupkg包的深度解析与安全防护指南

在.NET开发领域,nupkg包是开发者们不可或缺的工具。它不仅是代码分发和资源共享的核心载体,还贯穿了开发、构建、部署的全流程。今天,我们将深入探讨nupkg包的核心功能、打包发布流程以及安全防护措施,帮助你在.NET开发中更加得心…

Cursor 快速入门指南:从安装到核心功能

引言 Cursor 是一款融合 AI 能力的现代代码编辑器,旨在提升开发者的编码效率。本文将带您从零开始,快速掌握 Cursor 的完整使用流程 - 包括安装配置、项目初始化以及核心 AI 功能的应用。 正文 1. 安装与初始配置 1.1 下载与安装 Cursor 支持跨平台…

自然语言处理中probe探测是什么意思。

文章目录🔹 1. 英文单词的基本含义(动词 & 名词)✅ 作为动词(to probe):✅ 作为名词(a probe):🔹 2. 不同领域的具体含义🔹 3. 在机器学习/NL…

【记录】Ubuntu挂载home文件夹到磁盘

问题描述 服务器装好后,home文件夹一般存放各个用户的文件,默认的存储磁盘为系统磁盘,一般比较小,可能几百G,这对于服务器来讲,相当小了,所以需要对home文件夹进行重新调整。 我之前的博文 点击进入 相关配置在重启机器后,磁盘配置自动失效,即配置好后,home在大的磁…

【注意避坑】基于Spring AI 开发本地天气 mcp server,通义灵码测试MCP server连接不稳定,cherry studio连接报错

springboot 版本: 3.5.4 cherry studio版本:1.4.7 通义灵码版本: 2.5.13 文章目录 问题描述:1. 通义灵码添加mcp server ,配置测试2. cherry studio工具添加mcp server ,配置测试 项目源代码:解…

Paimon LSM Tree Compaction 策略

压缩怎么进行的这里的操作都是KValue,内部有row kind,标记了删除和插入MergeTreeCompactManager 是 Paimon 中 Merge-Tree 结构压缩任务的总调度中心。它的核心职责就是监控文件的层级状态(Levels),并在合适的时机&…

小米路由器3C刷OpenWrt,更换系统/变砖恢复 指南

基础篇看这里: 小米路由器3C如何安装OpenWrt官方编译的ROM - 哔哩哔哩 小米路由器 3C 刷入 Breed 和 OpenWrt - Snoopy1866 - 博客园 一、路由器注入 如果按照上面的文章, telnet、ftp一直连接失败,那么可以尝试看 这里: 获取路由器root权…

Spring Boot 项目启动时按需初始化加载数据

1、新建类,类上添加注解 Component ,该类用于在项目启动时处理数据加载任务; 2、该类实现 ApplicationRunner 接口,并重写 run 方法; 3、在重写的 run 方法里处理数据加载任务; 注意: 有定时加载…

MCP快速入门—快速构建自己的服务器

引言 随着大语言模型(LLM)技术的快速发展,如何扩展其能力边界成为开发者关注的重点。MCP(Model Capability Protocol)作为一种协议标准,允许开发者构建自定义服务器来增强LLM的功能。 正文内容 1. MCP核心概念与技术背景 MCP服务器主要提供三种能力类…

Vue 事件总线深度解析:从实现原理到工程实践

在 Vue 组件通信体系中,事件总线(Event Bus)是处理非父子组件通信的轻量解决方案。本文将从技术实现细节、工程化实践、内存管理等维度展开,结合源码级分析与典型场景,带你全面掌握这一核心技术点。​一、事件总线的技…

CMake Qt静态库中配置qrc并使用

CMake Qt序言环境代码序言 看网上这资料较少,且我理解起来有歧义,特地补充 环境 CMake:3.29.2 Qt:5.15.2 MSVC:2022 IDE:QtCreator 代码 方式一: 在CMakeLists.txt里,add_libr…

记录一下:成功部署k8s集群(部分)

前提条件:安装了containerd、docker 关闭了firewalld、selinux 配置了时间同步服务 chronyd 关闭swap分区等1、在控制节点、工作节点,安装kubelet、kubeadm、kubectlyum install -y kubelet-1.26.0 kubeadm-1.26.0 kubectl-1.26.0 …

Idea如何解决包冲突

Idea如何解决包冲突1.Error信息:JAR列表。 在扫描期间跳过不需要的JAR可以缩短启动时间和JSP编译时间。SLF4J: Class path contains multiple SLF4J bindings.SLF4J: Found binding in [jar:file:/E:/javapojects/stww-v4-gjtwt-seal/target/stww--v4-platform-proj…

python 协程学习笔记

目录 python 协程 通俗理解 Python 的 asyncio 协程,最擅长的是: 批量下载文件的例子: 协程的优势: python 协程 通俗理解 def my_coroutine():print("开始")x yield 1print("拿到了:", x)yi…

【学习笔记】蒙特卡洛仿真与matlab实现

概述 20 世纪 40 年代,由于电子计算机的出现, 借助计算机可以实现大量的随机抽样试验,为利用随机试验方法解决实际问题提供了便捷。 非常具代表性的例子是, 美国在第二次世界大战期间研制原子弹的“曼哈顿计划”中,为了…