【ArchSummit架构师峰会】探讨数据与人工智能相互驱动的关系>>> 了解详情
写点什么

openGauss 魔改 PG?它能兼容 Oracle 的数据库表吗?

  • 2020-10-21
  • 本文字数:5584 字

    阅读完需:约 18 分钟

openGauss魔改PG?它能兼容Oracle的数据库表吗?

本文由 dbaplus 社群授权转载。


openGauss 的前世今生


上一篇看到很多朋友留言对 openGauss 的历史疑问较多,本文开头就先把笔者道听途说来的 openGauss 历史作为杂谈在这里聊聊。


华为数据库最早诞生于运营商的需求,最初版本名称为 GMDB,后来基于 PostgreSQL-XC 进行整体改造,再配合自研的存储引擎,发布了 FusionInsight LibrA(天枰座),也就是大家听过较多的 MPPDB,目前官网上还能找到一些 FusionInsight LibrA 的资料。


同时在 2015 年,华为成立了另一项目组,纯自研了一款与 Oracle 非常相似的数据库,引擎名称为 Zenith。在 2015-2016 年左右,华为基于 MySQL 研发了一款云原生数据库 TaurusDB(这个时间段貌似有三款并行的数据库产品)。


2018 年左右,华为开始进行数据库整合,对数据库产品名定义为 GaussDB。针对不同的场景,分为 GaussDB 100(简单 OLTP 场景,单节点架构,基于 Zenith 引擎)、GaussDB 200(OLAP 及数仓场景,MPPDB 架构,基于 Libra 引擎)、GaussDB 300(HTAP 场景,分布式架构,貌似是基于 PostgreSQL-XL 改造)三个对外的产品,在 2019 年又进行了再次整合,将 GaussDB 100、GaussDB 300 合并,产品名称变为 GaussDB T(OLTP、HTAP 场景)、GaussDB A(OLAP 场景,原 Gauss 200)。


之后又基于华为云整体策略,Zenith 内核貌似是弃用了,启用原 Libra 内核(内核名称改成了轩辕),GaussDB A 变成了目前的华为云上 DWS 服务,GaussDB T 变成了 GaussDB for openGauss 服务,同时也将 openGauss 开源。由于 openGauss 是基于 GMDB 发展而来(也就是基于 PostgreSQL 的产品路线),所以命令行和元数据库的信息看起来还是 Postgres,不过底层的存储引擎与 PostgreSQL 有不少改动


openGauss 对 Oracle 表的兼容性验证


书接正传,接着上一篇本文继续基于 openGauss 1.0.0 版本对于 Oracle 中数据库表的兼容性进行验证


数据库的逻辑对象总共包含表、索引、约束、视图、序列、别名、函数、存储过程等。


表是数据库最基本的逻辑对象,也是作为承载数据的逻辑对象。在 Oracle 数据库中,数据库表分为堆表、临时表、表压缩、索引组织表、簇表、分区表以及嵌套表等 7 种类型。

一、堆表(heap table)

堆表是 Oracle 和 openGauss 默认表类型,堆表在数据写入时无需考虑行存放的顺序(按照写入的时间先后顺序存放),因此写入速度较高,但由于是无序存放,读取效率较低。在 Oracle 中,表的创建通常采用以下两种方式,openGauss 都可以兼容:


  • 在语句中定义表的字段结构:例如 create table test(id int),这种方式也是最常见的方式;在 openGauss 中,执行结果如下


postgres=# CREATE TABLE T_HEAP_TABLE(ID NUMBER,NAME VARCHAR2(32));CREATE TABLE
复制代码


  • 通过 select 语句的查询结果创建表:例如 create table test as select * from tmp_table,openGauss 中执行结果如下


postgres=# CREATE TABLE T_HEAP_TABLEASSELECT * FROM TMP_TEST;INSERT 0 0
复制代码

二、临时表

临时表可以理解为是一种特殊类型的表,用来保存临时数据的一个数据库对象。它只能存储在临时表空间,而非用户的表空间,对临时表的 DML 操作通常不记录事务日志。


Oracle 临时表分为事务级临时表和会话级临时表。事务级临时表的数据只保存在事务的生命周期中,会话级临时表能支持会话的完整生命周期。对于这两种级别的临时表,openGauss 都可以支持,实测结果如下:

1、事务级临时表

此类型的临时表中的数据仅在事务过程中有效,当事务提交后,临时表中的数据将被自动清除,但是临时表的结构以及元数据还存储在用户的数据字典中。在事务结束后,最好显式删除临时表,否则数据库会残留临时表的表结构和元数据。


  • 在语句中定义表的字段结构方式创建


postgres=# CREATE GLOBAL TEMPORARY TABLE T_TRANS_TMP(ID NUMBER,NAME VARCHAR2(32)) ON COMMIT DELETE ROWS;CREATE TABLE
复制代码


  • 通过 select 语句的查询结果创建表


postgres=# CREATE GLOBAL TEMPORARY TABLE T_TRANS_TMP ON COMMIT DELETE ROWSASSELECT * FROM TMP_TEST;INSERT 0 0
复制代码

2、会话级临时表

会话级临时表中的数据可以跨事务而存在,不过当该会话结束时,临时表中的数据将随着会话的结束而被丢弃。与事务级临时表相同,在会话结束后,会话级临时表的结构以及元数据还存储在用户的数据字典中,需显式手动清除。


  • 在语句中定义表的字段结构方式创建


postgres=# CREATE TEMPORARY TABLE T_CONN_TMP(ID NUMBER,NAME VARCHAR2(32)) ON COMMIT PRESERVE ROWS;CREATE TABLE
复制代码


  • 通过 select 语句的查询结果创建表


postgres=# CREATE TEMPORARY TABLE T_CONN_TMP ON COMMIT PRESERVE ROWSASSELECT * FROM TMP_TEST;INSERT 0 0
复制代码

三、表压缩

表压缩是对表数据进行压缩,达到节省空间的目的,压缩对于数据装载和 DML 操作有一定的 CPU 消耗。然而,这些消耗可以为 I/O 的减少而抵消。Oracle 常用的压缩方式有两种:基础压缩以及 OLTP 压缩。

1、基础压缩

基础压缩只在 direct path load 的时候才会生效,对于普通的 dml 语句 insert、update 不会发生压缩,openGauss 可以支持基础压缩。


postgres=# create table t_compress (id number) compress;CREATE TABLE
复制代码

2、OLTP 压缩

OLTP 压缩会对所有的 DML 生效,所以适用于 OLTP 系统。只有当新的 block 中的数据存放到达了阈值的时候才会引发块内的压缩操作,然后更多的数据加入到块中,再一次达到阈值,整个 block 会重新压缩,以达到最大程度的压缩级别。


这个过程会一直重复,直到 Oracle 数据库确定无法再从压缩上获得更高的效益。所以多数 OLTP 事务作用在压缩的块上面,会和未压缩的表上拥有相同的性能。只有部分操作会引发块内的压缩动作。OLTP 压缩功能 openGauss 目前无法支持。


postgres=# create table t_oltp_compress (id number) compress for oltp;<strong>ERROR:  syntax error at or near "for"</strong><strong>LINE 1: create table t_oltp_compress (id number) compress for oltp;</strong>
复制代码

四、索引组织表

索引组织表是以索引的方式保存表的数据,数据根据主键的顺序进行排列的,这样就提高了访问的速度。缺点是由于索引块保存所有的字段的信息,就需要更多的叶子页面来保存数据,数据量较大的时候会造成访问效率降低。


此外,如果主键频繁修改,对应的行也就需要磁盘位置频繁修改,行需要在不同的块之间相互移动。通常在以下情况,会考虑使用索引组织表:


  • 表的宽度(即一行的数据长度)有限;

  • 表的主键不会或极少更改;

  • 表主要用于查询,DML 操作较少;

  • 大部分的业务需求是根据主键查询行中其它列上的信息。


openGauss 目前版本不支持索引组织表,对于应用程序来说,索引组织表的使用方式与堆表并无差异。


postgres=# CREATE TABLE T_ORG_INDEX(ID NUMBER,NAME VARCHAR2(32),PRIMARY KEY(ID))organization index;ERROR:  syntax error at or near "organization index"LINE 6: )organization index;
复制代码

五、簇表

簇表也称为 Cluster,在没有数据表和索引的时候,Cluster 段是可以单独存在的。依据一定的规则,如连接键(Join Key),可以将多个数据表数据保存在同一个段中。并且依据一定场景实现快速检索连接。在 openGauss 中,无法兼容此功能。


postgres=# create cluster t_cluster (id number) size 600;<strong>ERROR:  syntax error at or near "cluster"</strong><strong>LINE 1: create cluster t_cluster (id number) size 600;</strong>
复制代码


在某些为了提高连接性能的情况下,可以考虑用列存与 partial cluster key 结合的方式替代,表定义中可以选取某一列或几列设置为 partial cluster key。


在导入数据时,按设置的列进行局部排序(默认每 70 个 CU 即 420 万行排序一次),生成的 CU 会聚集在一起,即 CU 的 min,max 会在一个较小的区间内。当查询时,where 条件含有这些列时,可产生良好的过滤效果。


postgres=# CREATE TABLE WAREHOUSE(    W_WAREHOUSE_SK            INTEGER               NOT NULL,    W_WAREHOUSE_ID            CHAR(16)              NOT NULL,    W_WAREHOUSE_NAME        VARCHAR(20)                   ,    PARTIAL CLUSTER KEY(W_WAREHOUSE_SK, W_WAREHOUSE_ID)) WITH (ORIENTATION = COLUMN);
复制代码

六、分区表

分区表是将一个大表按照一定的规则分解成多张具有独立存储空间的实体表。对于应用来说,逻辑上只有一个表,但在物理上这个表由多个物理分区组成。每个分区都是一个独立的对象,可以独自处理,也可以作为一个更大对象的一部分进行处理。分区表通常分为范围分区、列表分区、哈希分区以及复合分区。

1、范围分区

范围分区就是对数据表中的某个值的范围进行分区,根据某个值的范围,决定将该数据存储在哪个分区上。如根据序号分区,根据业务记录的创建日期进行分区等(联通每个月的账单记录就用的分区表存储)。在 openGauss 中,可以支持范围分区。


postgres=# CREATE TABLE t_range_partition  ( prod_id       NUMBER(6)  , cust_id       NUMBER  , time_id       DATE  , channel_id    CHAR(1)  , promo_id      NUMBER(6)  , quantity_sold NUMBER(3)  , amount_sold   NUMBER(10,2))  PARTITION BY RANGE (time_id)(PARTITION sales_q1_2006 VALUES LESS THAN (TO_DATE('01-APR-2006','dd-MON-yyyy')) TABLESPACE pg_default, PARTITION sales_q2_2006 VALUES LESS THAN (TO_DATE('01-JUL-2006','dd-MON-yyyy')) TABLESPACE pg_default, PARTITION sales_q3_2006 VALUES LESS THAN (TO_DATE('01-OCT-2006','dd-MON-yyyy')) TABLESPACE pg_default, PARTITION sales_q4_2006 VALUES LESS THAN (TO_DATE('01-JAN-2007','dd-MON-yyyy'))  TABLESPACE pg_default );CREATE TABLE
复制代码

2、列表分区

列表分区是根据所有可能的值,指定应该插入相应的分区,openGauss 当前版本无法支持列表分区。


postgres=# CREATE TABLE t_list_partition_table(id number,name varchar2(20),sales number(10, 2),state varchar2(2))PARTITION BY LIST (state)(PARTITION q1_northwest VALUES ('OR', 'WA'),PARTITION q1_southwest VALUES ('AZ', 'UT', 'NM'),PARTITION q1_northeast VALUES  ('NY', 'VM', 'NJ'),PARTITION q1_southeast VALUES ('FL', 'GA'),PARTITION q1_northcentral VALUES ('SD', 'WI'),PARTITION q1_southcentral VALUES ('OK', 'TX'));<strong>ERROR:  syntax error at or near "LIST"</strong><strong>LINE 6:    PARTITION BY LIST (state)</strong>
复制代码

3、散列分区

散列(HASH)分区通过在分区键值上执行一个散列函数来说决定数据的物理位置。散列分区把记录分布在比范围分区更多的分区上,这减少了 I/O 争用的可能性。openGauss 当前版本无法支持散列(HASH)分区。


postgres=# CREATE TABLE t_hash_partition(deptno NUMBER, deptname VARCHAR(32))PARTITION BY HASH(deptno)(PARTITION p1 TABLESPACE pg_default, PARTITION p2 TABLESPACE pg_default,PARTITION p3 TABLESPACE pg_default, PARTITION p4 TABLESPACE pg_default);<strong>ERROR:  syntax error at or near "HASH"</strong><strong>LINE 2:      PARTITION BY HASH(deptno)</strong>
复制代码

4、复合分区

对于分区表来说,数据倾斜的问题通常是最头疼的。为了解决这个问题,Oracle 提供了复合分区的功能。复合分区是先使用范围分区,然后在每个分区内再使用散列分区/列表分区的一种分区方法。不过目前版本 openGauss 无法支持复合分区。


postgres=# CREATE TABLE t_sub_partition( dept_no number, country varchar2(20), sale_date date)PARTITION BY RANGE(sale_date)SUBPARTITION BY LIST(country)( PARTITION q1_2012 VALUES LESS THAN('2012-Apr-01')( SUBPARTITION q1_europe VALUES ('FRANCE', 'ITALY'),SUBPARTITION q1_asia VALUES ('INDIA', 'PAKISTAN'),SUBPARTITION q1_americas VALUES ('US', 'CANADA') ),PARTITION q2_2012 VALUES LESS THAN('2012-Jul-01')( SUBPARTITION q2_europe VALUES ('FRANCE', 'ITALY'),SUBPARTITION q2_asia VALUES ('INDIA', 'PAKISTAN'),SUBPARTITION q2_americas VALUES ('US', 'CANADA') ),PARTITION q3_2012 VALUES LESS THAN('2012-Oct-01')( SUBPARTITION q3_europe VALUES ('FRANCE', 'ITALY'),SUBPARTITION q3_asia VALUES ('INDIA', 'PAKISTAN'),SUBPARTITION q3_americas VALUES ('US', 'CANADA') ),PARTITION q4_2012 VALUES LESS THAN('2013-Jan-01')( SUBPARTITION q4_europe VALUES ('FRANCE', 'ITALY'),SUBPARTITION q4_asia VALUES ('INDIA', 'PAKISTAN'),SUBPARTITION q4_americas VALUES ('US', 'CANADA') ) );<strong>ERROR:  syntax error at or near "SUBPARTITION"</strong><strong>LINE 3: SUBPARTITION BY LIST(country)</strong>
复制代码

七、嵌套表

嵌套表类似 C 语言中的结构体,可以把一个表结构定义为一个类型,在创建其他表的时候,可以将字段类型指向这个自定义类型。openGauss 中可以通过 create type 进行嵌套表定义。


postgres=# CREATE TYPE t_type AS (f1 int, f2 text);CREATE TYPEpostgres=# CREATE TABLE t_compfoo(a int, b t_type);CREATE TABLE
复制代码


总结


总体而言,openGauss 兼容 Oracle 常用表类型,索引组织表需要用集群索引方式进行改造。对于少数非常用数据类型,需要进行少量代码改造,可采取下列替代方案进行替换。


表类型是否兼容备注
堆表全部兼容
临时表全部兼容
表压缩部分兼容支持普通压缩模式,有DELTA、PREFIX、DICTIONARY、NUMSTR四种压缩算法供选择
索引组织表不兼容不支持
簇表不兼容不支持,部分情况可以考虑用partial cluster key替代
分区表部分兼容只支持范围分区
嵌套表功能兼容,但语法有部分改变


作者介绍


洪烨,openGauss Contributor,多年银行业系统架构设计及 DBA 实战经验,《DB2 数据库内部解析与性能调优》作者。


原文链接


openGauss魔改PG?它能兼容Oracle的数据库表吗?


2020-10-21 14:002932

评论

发布
暂无评论
发现更多内容

GaussDB(for MySQL)如何快速创建索引?华为云数据库资深架构师为您揭秘

华为云数据库小助手

华为云 GaussDB 华为云数据库 GaussDB(for MySQL)

被腾讯问蒙的各种Redis复杂问题

hanaper

Python——Map-Reduce

在即

9月日更

【Vuex 源码学习】第二篇 - vuex 插件安装 install 逻辑

Brave

源码 vuex 9月日更

Flutter 多引擎支持 PlatformView 以及线程合并解决方案

字节跳动终端技术

字节跳动 大前端 跨平台 火山引擎

Vue进阶(幺幺幺):实现浏览器全屏

No Silver Bullet

Vue 9月日更

爬虫初探: 重定向处理与新闻明细页解析

程序员架构进阶

Python 实战问题 9月日更 spider

数据湖特点

奔向架构师

数据湖 9月日更

链路压测中如何记录每一个耗时的请求

FunTester

性能测试 接口测试 测试框架 FunTester 链路压测

阿里菜鸟+腾讯IEG面经(阿里5面,腾讯8面)无限秽土转生

Java 程序员 架构 面试 计算机

低代码在这些方面充满优势

低代码小观

程序员 低代码 企业管理 开发平台 低代码开发

影像篡改与识别(三):人工智能时代

腾讯安全云鼎实验室

AI 影像识别

☕【JVM 技术指南】「理论总结笔记」Java 虚拟机垃圾回收认知和调优的"思南(司南)"【下部】

洛神灬殇

ZGC JVM G1垃圾回收器 9月日更

从特岗教师的需求金字塔,重新理解乡村、教育和科技

脑极体

算法裁员,释放出了哪些“恶之花”?

脑极体

使用PaddleNLP打造精准文献检索系统,看万方系统升级放大招!

百度大脑

人工智能 nlp 飞桨

如何利用极狐GitLab CI/CD 完成 Jenkins 的迁移

极狐GitLab

CI/CD #GitLab

百分点认知智能实验室:智能校对的技术原理和实践

百分点科技技术团队

关于技术团队搭建&管理的一些思考

LigaAI

团队管理

【直播预告】从校园学习到职场实践——淘系技术开学季特别分享系列

阿里巴巴大淘宝技术

程序员 应聘tips

内网渗透攻击技术的利用

网络安全学海

网络安全 信息安全 渗透测试 WEB安全 安全漏洞

【架构实战营作业】模块三:学生管理系统架构设计文档

聆息

微前端拆分实践

Teobler

大前端 服务拆分

挑战进阶教程,和MindSpore更近一步!

Geek_6cdeb6

mindspore

多租户的共享与隔离

金蝶天燕云

云计算 多租户

JS完美收官之——闭包

法医

9月日更

区块链将帮助监管科技突破壁垒,刺激金融市场的监管活力

CECBC

学生管理系统详细设计

缘分呐

设计 学生管理系统架构

推荐一个Mac端的截图工具

IT蜗壳-Tango

9月日更

架构实战训练营|作业|模块3

Frode

架构实战

跟着我乔鲁诺学面试(大误)

姬翔

9月日更

openGauss魔改PG?它能兼容Oracle的数据库表吗?_数据库_dbaplus社群_InfoQ精选文章