openGauss一种可能是目前最快的从ORACLE同步数据到MogDB(openGauss)的方式

Posted 耀阳居士

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了openGauss一种可能是目前最快的从ORACLE同步数据到MogDB(openGauss)的方式相关的知识,希望对你有一定的参考价值。

【openGauss】一种可能是目前最快的从ORACLE同步数据到MogDB(openGauss)的方式

一、前言

目前openGauss支持oracle中的绝大部分数据类型,基本上不用考虑类型转换的问题。所以从oracle到MogDB(openGauss)的数据同步无非就是从oracle里查出来再插入到MogDB(openGauss)中,只是查出来的结果是存成文件还是放内存而已。
用文件的形式,oracle端有sqluldr2可以快速导出,MogDB(openGauss)端可以用copy命令快速载入;
如果是放内存,则需要一定量的代码开发,而且目前通用的数据同步工具在导入时,大多用的是逐行insert命令,效率很低。
所以,是否存在一种可能,只利用现有的工具,就能实现数据的高速同步且不需要存文件?

在说这个方案前,先简单说明一下这个方案的几个知识点。

二、知识点

1.sqluldr2

sqluldr2是楼方鑫针对Oracle数据库开发的数据快速导出工具,应该绝大多数oracle用户都用过,因为它依旧是目前从oracle中导出文本数据最快的方式了,速度远超oracle官方的sqlplus spool导出。但是大多数人基本上都只使用其导出文件的功能,而不知道这个工具还可以导出标准输出(所谓标准输出即不生成文件,直接打印在屏幕上)
sqluldr2完整文档:https://www.doc88.com/p-6522591706862.html

2.gsql/psql(\\copy 元命令)

gsql/psql的"\\copy"元命令
(注意区别于sql命令中的"copy",“copy"是服务器端的,”\\copy"是客户端的),
常用于和表和文件之间的导入和导出,效率很快,因为已经指定了表,不需要再进行字段类型的识别,绕开了sql解析引擎,直接写入表中。
但大多数人很少用到 stdin和stdout(除非是基于其他高级语言进行数据导入导出的开发),这里的stdin即为标准输入,如果执行"\\copy 表名 from stdin",则会让你继续输入数据,然后客户端会把数据保存到对应的表中。

3.gsql/psql (-c参数)

gsql/psql 的 "-c"参数,可以在连接数据库后马上执行sql命令然后断开登录

4.linux ( | 管道符)

linux的管道符"|",可以用于输入的重定向,即把前面一条命令的输出,作为后面一条命令的输入

三、方案说明

通过以上内容,很自然的可以联想到一种方式,即使用sqluldr2的标准输出,直接作为gsql \\copy的标准输入。所谓的两点之间直线最短,用最快的导出加上最快的导入,且省去中间存储文件的阶段,理想状态下,这个速度仅受限于源端或目标端最慢的那一端,比如导出7分钟,导入8分钟,一般总计传输时间就是15分钟,但是用本文的方案,这个传输时间可能就只有8分钟了,因为它是导入导出同时进行的!

四、操作步骤

  1. 需要有个服务器能同时连接oracle及MogDB(openGauss),当然直接用这两个服务器之一也可以,只是注意要安装另一个数据的客户端,本文测试是在mogdb数据库的服务器上执行的
  • oracle客户端下载链接
    https://www.oracle.com/cn/database/technologies/instant-client/linux-x86-64-downloads.html
  • MogDB(openGauss)没有提供单独的客户端压缩包,客户端在数据库的安装包中对应的tools压缩包,比如
    MogDB-3.0.1-CentOS-64bit-tools.tar.gz
    https://mogdb.io/downloads/mogdb/
  1. 安装客户端,这两个客户端的安装方式差不多,就是解压,然后配置环境变量LD_LIBRARY_PATH,比如配置连接Oracle的环境变量如下(如果需要永久配置则要修改对应的配置文件)
export LD_LIBRARY_PATH=/opt/mogdb/instantclient_21_7:$LD_LIBRARY_PATH
  1. 下载sqluldr2程序
    这个就自己在网上搜吧,基本下载下来是一个压缩包,里面有两个windows版的和两个linux版的,我们需要的是"sqluldr2_linux64_10204.bin"这个文件,下完后可以把文件名改短点,比如"sqluldr2"

  2. 先找个小表测试下sqluldr2能否导出文件,文件正常生成,说明oracle客户端配置正确

./sqluldr2 scott/tiger@192.168.163.108/orcl query=emp quote=0x22 field="," degree=8 file=123.csv
[omm@MiWiFi-R3G-srv mogdb]$ cat 123.csv
7369,"SMITH","CLERK",7902,"1980-12-17 00:00:00",800,,20
7499,"ALLEN","SALESMAN",7698,"1981-02-20 00:00:00",1600,300,30
7521,"WARD","SALESMAN",7698,"1981-02-22 00:00:00",1250,500,30
7566,"JONES","MANAGER",7839,"1981-04-02 00:00:00",2975,,20
7654,"MARTIN","SALESMAN",7698,"1981-09-28 00:00:00",1250,1400,30
7698,"BLAKE","MANAGER",7839,"1981-05-01 00:00:00",2850,,30
7782,"CLARK","MANAGER",7839,"1981-06-09 00:00:00",2450,,10
7788,"SCOTT","ANALYST",7566,"1987-04-19 00:00:00",3000,,20
7839,"KING","PRESIDENT",,"1981-11-17 00:00:00",5000,,10
7844,"TURNER","SALESMAN",7698,"1981-09-08 00:00:00",1500,0,30
7876,"ADAMS","CLERK",7788,"1987-05-23 00:00:00",1100,,20
7900,"JAMES","CLERK",7698,"1981-12-03 00:00:00",950,,30
7902,"FORD","ANALYST",7566,"1981-12-03 00:00:00",3000,,20
7934,"MILLER","CLERK",7782,"1982-01-23 00:00:00",1300,,10
  1. 在目标端建立一个同样的表
gsql -d postgres -r -p 26000
create schema scott; create table SCOTT.EMP ( empno NUMBER(4) not null, ename VARCHAR2(10), job VARCHAR2(9), mgr NUMBER(4), hiredate DATE, sal NUMBER(7,2), comm NUMBER(7,2), deptno NUMBER(2) );
  1. ★测试通过管道传输数据,没有报错
./sqluldr2 scott/tiger@192.168.163.108/orcl query=emp quote=0x22 field="," degree=8 file=- |gsql -d postgres -Umogdb -WEnmo@123 -hlocalhost -p26000 -c "\\copy scott.emp from stdin DELIMITER \',\' quote \'\\"\' csv"
  1. 在目标端查询scott.emp表,数据和源端一致
MogDB=# select * from scott.emp;
 empno | ename  |    job    | mgr  |      hiredate       |   sal   |  comm   | deptno 
-------+--------+-----------+------+---------------------+---------+---------+--------
  7369 | SMITH  | CLERK     | 7902 | 1980-12-17 00:00:00 |  800.00 |         |     20
  7499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 00:00:00 | 1600.00 |  300.00 |     30
  7521 | WARD   | SALESMAN  | 7698 | 1981-02-22 00:00:00 | 1250.00 |  500.00 |     30
  7566 | JONES  | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 |         |     20
  7654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 |     30
  7698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 |         |     30
  7782 | CLARK  | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 |         |     10
  7788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 |         |     20
  7839 | KING   | PRESIDENT |      | 1981-11-17 00:00:00 | 5000.00 |         |     10
  7844 | TURNER | SALESMAN  | 7698 | 1981-09-08 00:00:00 | 1500.00 |    0.00 |     30
  7876 | ADAMS  | CLERK     | 7788 | 1987-05-23 00:00:00 | 1100.00 |         |     20
  7900 | JAMES  | CLERK     | 7698 | 1981-12-03 00:00:00 |  950.00 |         |     30
  7902 | FORD   | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 |         |     20
  7934 | MILLER | CLERK     | 7782 | 1982-01-23 00:00:00 | 1300.00 |         |     10
(14 rows)

五、简单性能测试

由于硬盘空间不够,测试数据库也是虚拟机和docker中的,就不做详细的测试了,只做个简单的100万数据测试

SQL> select count(1) from scott.T_TEST1; COUNT(1) ---------- 1000000

直接管道传输,用时7s

[omm@MiWiFi-R3G-srv mogdb]$ echo $(date) Thu Sep 15 04:24:23 EDT 2022 [omm@MiWiFi-R3G-srv mogdb]$ ./sqluldr2 scott/tiger@192.168.163.108/orcl query=SCOTT.T_TEST1 quote=0x22 field="," degree=8 file=- |gsql -d postgres -Umogdb -WEnmo@123 -hlocalhost -p26000 -c "\\copy SCOTT.T_TEST1 from stdin DELIMITER \',\' quote \'\\"\' csv" [omm@MiWiFi-R3G-srv mogdb]$ echo $(date) Thu Sep 15 04:24:30 EDT 2022

在目标端删除测试表,重建,然后用导出文件再导入的方式,导出5s,导入7s,一共12s

[omm@MiWiFi-R3G-srv mogdb]$ echo $(date) Thu Sep 15 04:20:00 EDT 2022 [omm@MiWiFi-R3G-srv mogdb]$ ./sqluldr2 scott/tiger@192.168.163.108/orcl query=SCOTT.T_TEST1 quote=0x22 field="," degree=8 file=1234.csv 0 rows exported at 2022-09-15 04:20:00, size 0 MB. 1000000 rows exported at 2022-09-15 04:20:05, size 48 MB. output file 1234.csv closed at 1000000 rows, size 48 MB. [omm@MiWiFi-R3G-srv mogdb]$ echo $(date) Thu Sep 15 04:20:05 EDT 2022
[omm@MiWiFi-R3G-srv mogdb]$ echo $(date) Thu Sep 15 04:23:03 EDT 2022 [omm@MiWiFi-R3G-srv mogdb]$ gsql -d postgres -Umogdb -WEnmo@123 -hlocalhost -p26000 -c "\\copy SCOTT.T_TEST1 from \'/opt/mogdb/1234.csv\' DELIMITER \',\' quote \'\\"\' csv" [omm@MiWiFi-R3G-srv mogdb]$ echo $(date) Thu Sep 15 04:23:10 EDT 2022

大致判断,这次测试的速度上限受导入影响,如果再优化一下数据库相关参数,耗时可以更低,但这里主要是提供一个可行的快速传输数据的思路,就不去做参数调整了。

六、总结

了解了这个原理,完全可以写一个程序或者shell脚本,通过把配置进行参数化处理,来制作一个Oracle到openGauss的通用高速数据传输工具。

四openGauss存储引擎

一、简介

openGauss存储引擎是可插拔、自组装的,支持多个存储引擎来满足不同场景的业务诉求,目前支持行存储引擎、列存储引擎和内存引擎。

早期计算机程序通过文件系统管理数据,到了20世纪60年代这种方式就开始不能满足数据管理要求了,用户逐渐对数据并发写入的完整性、高效检索提出更高的要求。由于机械磁盘的随机读写性能问题,从20世纪80年代开始,大多数数据库一直在围绕着减少随机读写磁盘进行设计。主要思路是把对数据页面的随机写盘转化为对WAL(Write Ahead Log,预写式日志)日志的顺序写盘,WAL日志持久化完成,事务就算提交成功,数据页面异步刷盘。但是随着内存容量变大、保电内存、非易失性内存的发展,以及SSD技术逐渐的成熟,IO性能极大提高,经历了几十年发展的存储引擎需要调整架构来发挥SSD的性能和充分利用大内存计算的优势。随着互联网、移动互联网的发展,数据量剧增,业务场景多样化,一套固定不变的存储引擎不可能满足所有应用场景的诉求。因此现在的DBMS需要设计支持多种存储引擎,根据业务场景来选择合适的存储模型。

1、数据库存储引擎要解决的问题

  • 存储的数据必须要保证ACID:原子性、一致性、隔离性、持久性。
  • 高并发读写,高性能。
  • 数据高效存储和检索能力。

2、openGauss存储引擎概述

openGauss整个系统设计支持多个存储引擎来满足不同场景的业务诉求。当前openGauss存储引擎有以下3种:
行存储引擎。主要面向OLTP(Online Transaction Processing,在线交易处理)场景设计,例如订货发货,银行交易系统。
列存储引擎。主要面向OLAP(Online Analytical Processing,联机分析处理)场景设计,例如数据统计报表分析。
内存引擎。主要面向极致性能场景设计,例如银行风控场景。

创建表的时候可以指定行存储引擎、列存引擎的表、内存引擎的表,支持一个事务里包含对3种引擎表的DML(Data Manipulation Language,
数据操作语言)操作,可以保证事务ACID性质。

1) storage源码组织
storage源码目录为:/src/gausskernel/storage。storage源码文件如表1所示。
表1 storage源码文件
storage storage源码文件
access 基础行存储引擎方法cbtree、hash、heap、index、…
buffer 缓冲区
freespace 空闲空间管理
ipc 进程内交互
large_object 大对象处理
remote 远程读
replication 复制备份
smgr 存储管理
cmgr 公共缓存方法
cstore 列存储引擎
dfs 分布式文件系统
file 文件类
lmgr 锁管理
mot 内存引擎
page 数据页

3、行存储引擎

openGauss的行存储引擎设计上支持MVCC(Multi-Version Concurrency Control,多版本并发控制),采用集中式垃圾版本回收机制,可以提供OLTP业务系统的高并发读写要求。支持存储计算分离架构,存储层异步回放日志。如图1所示。

四、openGauss存储引擎_数据库


行存储引擎的关键技术有:
基于CSN(Commit Sequence Number,待提交事务的序列号,它是一个64位递增无符号数)的MVCC并发控制机制,集中式垃圾数据清理。
并行刷日志,并行恢复。传统数据库一般都采用串行刷日志的设计,因为日志有顺序依赖关系,例如一个是事务产生的redo/undo log是有前后依赖关
系的。openGauss的日志系统采用多个logwriter线程并行写的机制,充分发挥SSD的多通道IO能力。
基于大内存设计的Buffer manager。

4、列存储引擎

传统行存储数据压缩率低,必须按行读取,即使读取一列也必须读取整行。openGauss创建表的时候,可以指定行存储还是列存储。列存储表也支持DML操作,也支持MVCC。列存储架构如图2所示。

四、openGauss存储引擎_数据库_02

列存储引擎有以下优势:
列的数据特征比较相似,适合压缩,压缩比很高。
当表列的个数比较多,但是访问的列个数比较少时,列存可以按需读取列数据,大大减少不必要的读IO,提高查询性能。
基于列批量数据Vector(向量)的运算,CPU的cache命中率比较高,性能比较好。列存储引擎更适合OLAP大数据统计分析的场景。

1) 列存储源码组织
列存储源码目录为:/src/gausskernel/storage/cstore。列存储源码文件如表2所示。

表2 列存储源码文件
cstore 列存储源码文件
compression 数据压缩与解压
cstore_allocspace 空间分配
cstore_am 列存储公共API
cstore_***_func 支持函数
cstore_psort 列内排序
cu 数据压缩单元
cucache_mgr 缓存管理器
custorage 持久化存储
cstore_delete 删除方法
cstore_update 更新方法
cstore_vector 缓冲区实现
cstore_rewrite SQL重写
cstore_insert 插入方法
cstore_mem_alloc 内存分配

5、内存引擎

openGauss引入了MOT(Memory-Optimized Table,内存优化表)存储引擎,它是一种事务性行存储,针对多核和大内存服务器进行了优化。MOT是openGauss数据库出色的生产级特性(Beta版本),它为事务性工作负载提供更高的性能。MOT完全支持ACID特性,并包括严格的持久性和高可用性支持。企业可以在关键任务、性能敏感的在线事务处理(OLTP)中使用MOT,以实现高性能、高吞吐、可预测低延迟以及多核服务器的高利用率。MOT尤其适合在多路和多核处理器的现代服务器上运行,例如基于ARM(Advanced RISC Machine,高级精简指令集计算机器)/鲲鹏处理器的华为TaiShan服务器,以及基于x86的戴尔或类似服务器。MOT存储引擎如图3所示。

四、openGauss存储引擎_数据_03

MOT与基于磁盘的普通表并排创建。MOT的有效设计实现了几乎完全的SQL覆盖,并且支持完整的数据库功能集,如存储过程和自定义函数。通过完全存、
储在内存中的数据和索引、非统一内存访问感知(NUMA-aware)设计、消除锁和锁存争用的算法以及查询原生编译,MOT可提供更快的数据访问和更高
效的事务执行。MOT有效的几乎无锁的设计和高度调优的实现,使其在多核服务器上实现了卓越的近线性吞吐量扩展。

MOT的高性能(查询和事务延迟)、高可扩展性(吞吐量和并发量)等特点,在某些情况下低成本(高资源利用率)方面拥有显著优势。
低延迟(Low Latency):提供快速的查询和事务响应时间。
高吞吐量(High Throughput):支持峰值和持续高用户并发。
高资源利用率(High Resource Utilization):充分利用硬件。

MOT的关键技术如下:
内存优化数据结构:以实现高并发吞吐量和可预测的低延迟为目标,所有数据和索引都在内存中,不使用中间页缓冲区,并使用持续时间最短的锁。数
据结构和所有算法都是专门为内存设计而优化的。
免锁事务管理:MOT在保证严格一致性和数据完整性的前提下,采用乐观的策略实现高并发和高吞吐。在事务过程中,MOT不会对正在更新的数据行的任
何版本加锁,从而大大降低了一些大内存系统中的争用。
免锁索引:由于内存表的数据和索引完全存储在内存中,因此拥有一个高效的索引数据结构和算法非常重要。MOT索引机制基于领域前沿的树结构
Masstree,一种用于多核系统的快速和可扩展的键值(Key Value,KV)存储索引,以B+树的Trie实现。通过这种方式,高并发
工作负载在多核服务器上可以获得卓越的性能。同时MOT应用了各种先进的技术以优化性能,如优化锁方法、高速缓存感知和内存预取。
NUMA-aware的内存管理:MOT内存访问的设计支持非统一内存访问(NUMA,Non-Uniform Memory Access)感知。NUMA-aware算法增强了内存中
数据布局的性能,使线程访问物理上连接到线程运行的核心的内存。这是由内存控制器处理的,不需要通过使用互连(如英特尔
QPI(Quick Path Interconnect,快速路径互连))进行额外的跳转。MOT的智能内存控制模块,为各种内存对象预先分配了
内存池,提高了性能、减少了锁、保证了稳定性。
高效持久性:日志和检查点是实现磁盘持久化的关键能力,也是ACID的关键要求之一。目前所有的磁盘(包括SSD和NVMe(Non-Volatile Memory
express,非易失性高速传输总线))都明显慢于内存,因此持久化是基于内存数据库引擎的瓶颈。作为一个基于内存的存储引擎,
MOT的持久化设计必须实现各种各样的算法优化,以确保持久化的同时还能达到设计时的速度和吞吐量目标。
高SQL覆盖率和功能集:MOT通过扩展的openGauss外部数据封装(Foreign Data Wrapper,FDW)以及索引,几乎支持完整的SQL范围,包括存储过
程、用户定义函数和系统函数调用。
使用PREPARE语句的查询原生编译:通过使用PREPARE客户端命令,可以以交互方式执行查询和事务语句。这些命令已被预编译成原生执行格式,也称
为Code-Gen或即时(Just-in-Time,JIT)编译。这样可以实现平均30%的性能提升。
MOT和openGauss数据库的无缝集成:MOT是一个高性能的面向内存优化的存储引擎,已集成在openGauss软件包中。MOT的主内存引擎和基于磁盘的存
储引擎并存,以支持多种应用场景,同时在内部重用数据库辅助服务,如WAL重做日志、复制、检查点和恢复高可用性等。

1) 内存引擎源码组织
内存引擎源码目录为:/src/gausskernel/storage/mot。内存引擎源码文件如表3所示。
表3 内存引擎源码文件
mot 内存引擎源码文件
concurrency_control 并发控制管理
infra 辅助与配置函数
memory 内存数据管理
storage 持久化存储
system 全局控制API
utils 日志等通用方法

以上是关于openGauss一种可能是目前最快的从ORACLE同步数据到MogDB(openGauss)的方式的主要内容,如果未能解决你的问题,请参考以下文章

Vert.x!目前最快的 Java 框架

Vert.x!这是目前最快的 Java 框架

四openGauss存储引擎

通过服务器排序并确定最快 ping 的简化方式

❤️‍如何使用pgloader迁移MySQL数据库至openGauss❤️‍

openEuler-22.03系统安装openGauss3.0.0 企业版过程中遇到的坑