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


openGauss魔改PG?它能兼容Oracle的数据库表吗?文章插图
作者介绍
洪烨 , openGauss Contributor , 多年银行业系统架构设计及DBA实战经验 , 《DB2数据库内部解析与性能调优》作者 。
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_TABLE
AS
SELECT * 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 ROWS
AS
SELECT * FROM TMP_TEST;
INSERT 0 0
2、会话级临时表
会话级临时表中的数据可以跨事务而存在 , 不过当该会话结束时 , 临时表中的数据将随着会话的结束而被丢弃 。 与事务级临时表相同 , 在会话结束后 , 会话级临时表的结构以及元数据还存储在用户的数据字典中 , 需显式手动清除 。