热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

db2查看表结构_技术分享|openGaussOracle兼容性评估(二)数据库表

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

3e8cf0b8f73ca815545870252b135acd.gif

作者介绍

洪烨,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、会话级临时表

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

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

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 ROWS

AS

SELECT * 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;

ERROR:  syntax error at or near "for"

LINE 1: create table t_oltp_compress (id number) compress for oltp;

四、索引组织表

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

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

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

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

  • 表主要用于查询,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;

ERROR:  syntax error at or near "cluster"

LINE 1: create cluster t_cluster (id number) size 600;

在某些为了提高连接性能的情况下,可以考虑用列存与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'));  

ERROR:  syntax error at or near "LIST"

LINE 6:    PARTITION BY LIST (state)  

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);   

ERROR:  syntax error at or near "HASH"

LINE 2:      PARTITION BY HASH(deptno) 

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') ) ); 

ERROR:  syntax error at or near "SUBPARTITION"

LINE 3: SUBPARTITION BY LIST(country)

七、嵌套表

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

postgres=# CREATE TYPE t_type AS (f1 int, f2 text);

CREATE TYPE

postgres=# CREATE TABLE t_compfoo(a int, b t_type);

CREATE TABLE

总结

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

表类型

是否兼容

备注

堆表

全部兼容

临时表

全部兼容

表压缩

部分兼容

支持普通压缩模式,有DELTA、PREFIX、DICTIONARY、NUMSTR四种压缩算法供选择

索引组织表

不兼容

不支持

簇表

不兼容

不支持,部分情况可以考虑用partial cluster key替代

分区表

部分兼容

只支持范围分区

嵌套表

功能兼容,但语法有部分改变

相关阅读:

  • openGauss可替代Oracle吗?从字段类型说起……


2020 DAMS中国数据智能管理峰会即将于10月30日在上海举办,部分精彩议题先睹为快:

  • 腾讯《腾讯游戏大数据资产管理实战:元数据管理与数据治理

  • 京东《京东EB级全域大数据平台建设和治理之路》

  • 阿里《大规模容器云基础设施环境架构、管理与运维》

  • 工商银行《DevOps转型的探索与实践》

  • 中国银联《从自研演进看分布式数据库》

  • 民生银行《开源数据库MySQL在民生银行的应用实践》

  • 平安银行《“传统+互联网”混合CMDB及运营中台实践》

  • 中国联通《大数据资产管理平台的设计、研发、运营实践》

  • AWS《基于数据湖构建云上的数据分析架构》

  • 今日头条字节跳动数据治理实践》

  • 苏宁《苏宁大规模智能告警收敛与告警根因的实践》

  • 滴滴《万亿级消息队列Kafka在滴滴的实践》

c28a8653f79766ee4af4c312a7f3f3df.png




推荐阅读
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 本文详细介绍了MysqlDump和mysqldump进行全库备份的相关知识,包括备份命令的使用方法、my.cnf配置文件的设置、binlog日志的位置指定、增量恢复的方式以及适用于innodb引擎和myisam引擎的备份方法。对于需要进行数据库备份的用户来说,本文提供了一些有价值的参考内容。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • 先看一段错误日志:###Errorqueryingdatabase.Cause:com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransie ... [详细]
  • MySQL多表数据库操作方法及子查询详解
    本文详细介绍了MySQL数据库的多表操作方法,包括增删改和单表查询,同时还解释了子查询的概念和用法。文章通过示例和步骤说明了如何进行数据的插入、删除和更新操作,以及如何执行单表查询和使用聚合函数进行统计。对于需要对MySQL数据库进行操作的读者来说,本文是一个非常实用的参考资料。 ... [详细]
  • 深入理解Java虚拟机的并发编程与性能优化
    本文主要介绍了Java内存模型与线程的相关概念,探讨了并发编程在服务端应用中的重要性。同时,介绍了Java语言和虚拟机提供的工具,帮助开发人员处理并发方面的问题,提高程序的并发能力和性能优化。文章指出,充分利用计算机处理器的能力和协调线程之间的并发操作是提高服务端程序性能的关键。 ... [详细]
  • 2021最新总结网易/腾讯/CVTE/字节面经分享(附答案解析)
    本文分享作者在2021年面试网易、腾讯、CVTE和字节等大型互联网企业的经历和问题,包括稳定性设计、数据库优化、分布式锁的设计等内容。同时提供了大厂最新面试真题笔记,并附带答案解析。 ... [详细]
  • ElasticSerach初探第一篇认识ES+环境搭建+简单MySQL数据同步+SpringBoot整合ES
    一、认识ElasticSearch是一个基于Lucene的开源搜索引擎,通过简单的RESTfulAPI来隐藏Lucene的复杂性。全文搜索,分析系统&# ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 基于事件驱动的并发编程及其消息通信机制的同步与异步、阻塞与非阻塞、IO模型的分类
    本文介绍了基于事件驱动的并发编程中的消息通信机制,包括同步和异步的概念及其区别,阻塞和非阻塞的状态,以及IO模型的分类。同步阻塞IO、同步非阻塞IO、异步阻塞IO和异步非阻塞IO等不同的IO模型被详细解释。这些概念和模型对于理解并发编程中的消息通信和IO操作具有重要意义。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • mysql-cluster集群sql节点高可用keepalived的故障处理过程
    本文描述了mysql-cluster集群sql节点高可用keepalived的故障处理过程,包括故障发生时间、故障描述、故障分析等内容。根据keepalived的日志分析,发现bogus VRRP packet received on eth0 !!!等错误信息,进而导致vip地址失效,使得mysql-cluster的api无法访问。针对这个问题,本文提供了相应的解决方案。 ... [详细]
  • 在Oracle11g以前版本中的的DataGuard物理备用数据库,可以以只读的方式打开数据库,但此时MediaRecovery利用日志进行数据同步的过 ... [详细]
author-avatar
手机用户2602908963
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有