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

数仓中的数据对象及相关关系的解读

为实现不同的功能,GaussDB(DWS)提供了不同的数据对象类型,包括索引、行存表、列存表及其辅助表等。这些数据对象在特定

为实现不同的功能,GaussDB(DWS)提供了不同的数据对象类型,包括索引、行存表、列存表及其辅助表等。这些数据对象在特定的条件下实现不同的功能,为数据库的快速高效提供了保证,本文对部分数据对象进行介绍。


1. 索引(index)

索引是关系型数据库中对某一列或者多个列的值进行预排序的数据结构。如果数据库的记录非常多,通过建立索引可以获得非常快的查询速度,当对某一列建立索引之后,通过该列进行相关查询时数据库系统就不必扫描整个表,而是直接通过索引定位到符合条件的记录,在一定程度上能够大幅提升查询得速度。

假如需要执行如下的语句进行查询:

SELECT name FROM test_1 WHERE number =10;

一般情况下数据库需要对每一行进行遍历查询,直到找到所有满足条件 number=10 的元组信息。当数据库的记录很多,而满足 where 条件的记录又很少时,顺序扫描的性能就会很差。这时如果在表 test_1 的 number 属性上建立索引,用于快速定位需要匹配的元组信息,数据库只需要根据索引的数据结构进行搜索,由于常用的索引结构有 B-Tree、Hash、GiSt、GIN 等,这些索引结构的查询都是快速高效的,因此可以在少数几步内完成查询,大大提高了查询效率。

对表 test_1 的 number 属性建立索引语句如下:

CREATE INDEX numberIndex ON test_1(number);

由于 GaussDB 里的所有索引都是 “从属索引”,索引在物理文件上与原来的表文件分离,执行上述创建索引语句后,系统会生成 relname 为 numberIndex 的索引类型。表和索引都是数据库对象,在 pg_class 里会有该索引的记录,有与之相对应的 oid,同时在 pg_index 表里会记录索引及其对应主表的信息。对应属性信息如图 1 所示。

图 1 pg_index 部分属性


2.toast 表

toast(The Oversized-Atttibute Storage Techhnique)即超尺寸字段存储技巧,是数据库提供的一种存储大数据的机制。只有一些具有变长表现形式的数据类型才会支持 toast,比如 TEXT 类型。由于在 GaussDB (DWS) 的行存储方式中,一条数据的所有列组合在一起称之为一个 tuple,多个 tuple 组成一个 page。page 是数据在文件存储中的基本单位,其大小是固定的且只能在编译器指定,之后无法修改,默认发大小为 8KB,当某行数据很大超过 page 的大小时,数据库系统就会启动 toast,对数据进行压缩和切片。实际数据以行外存储的形式存储在另外一张表中,这张表就是 toast 表。

当一张表的任何一个属性是可以 toast 的,则这张表会有一张关联的 toast 表,在 pg_class 里表的 reltoastrelid 属性里记录了该 toast 表的 oid,如果没有关联的 toast 表,reltoastrelid=0。那么如何判断一张表的属性是否是可以 toast 的呢?我们可以在表的 Storage 选项中查看对应属性的存储策略。有以下四种不同的存储策略:


  • PLAIN:避免压缩或者行外存储;此外,它禁止为变长类型使用单字节的头。 这只对那些不能 TOAST 的数据类型的列才有可能。
  • EXTENDED:允许压缩和行外存储。 这是大多数 TOAST 数据类型的缺省策略。首先会尝试对数据进行压缩, 如果行仍然太大,则进行行外存储。
  • EXTERNAL:允许行外存储,但是不许压缩。 使用 EXTERNAL,将使那些数据类型为 text 和 bytea 的字段上的子字符串操作更快 (代价是增加了存储空间),因为这些操作是经过优化的:如果行外数据没有压缩,那么它们只会获取需要的部分。
  • MAIN:允许压缩,但不允许行外存储。 实际上,在这样的字段上仍然会进行行外存储, 但只是作为没有办法把数据行变得更小以使之足以放置在一个页面中的最后选择。

假如创建表语句如下:

CREATE TABLE test_t(id int,description text);

创建了一张 test_t 表,该表有 id 和 description 两个属性,分别属于 int 和 text 类型,查看该表的属性对应的 Storage 策略:

图 2 test_t 表相关信息

我们可以看出 description 属性的 Storage 策略为 EXTENDED,是可以 toast 的,系统会为 test_t 表创建一张关联的 toast 表。

图 3 test_t 表对应 toast 表

通过查询 pg_class,可以的看到表 test_t 关联的 toast 表的 oid 为 52579,进一步以此 oid 为条件在 pg_class 里就会得到 toast 表的相关信息。

图 4 toast 表相关信息

下图为 test_t 表和其对应的 toast 表之间的关系,以及 toast 表一些基本属性的介绍。

图 5 test_t 与其 toast 表关系图


3.cudesc 表

GaussDB (DWS) 除了提供行存储方式外,还支持列存储方式。列存储方式在数据压缩、列批量数据的运算、大数据统计分析等场景中有着显著的优势。CU(Compress Unit)压缩单元是列存储的最小单位,每列默认 60000 行存储在一个 CU 中,CU 生成后数据 固定不可更改。CUDesc 本身是一张行存表,它用来辅助记录列存表的 cu 信息,该表的每一行描述一个 CU,包括最大值最小值以及 CU 在文件中的偏移量和大小,连续多个行中各个不同的列的 cu_id 相同,可以认为就是把连续多个行截断拿出来,然后再根据不同的列,放到不同的 cu 中,这些 CU 所在的行数都是一致的,用一个 cu_id 表示,但是 col_id 不一样。同时还增加了一个 col_id=-10 的列,这个列为 VCU,表示这些连续的行中,有哪些行已经是被删除了,用 delete_map 记录删除信息。如图 6 所示。

图 6 cudesc 表示意图

每张列存表都有一张对应的 CUDesc 表,CUDesc 表的 oid 可以在 pg_class 中对应列存表元组的 relcudescrelid 属性中查到,所有 CUDesc 表默认存储在 namespace oid = 100,name 为 cstore 的 namespace 下。


4.delta 表

在列存储方式中,无论是向列存表中插入 1 条还是 60000 条数据,都只会生成一个 CU,在多次插入少量数据时,不能有效的利用列存压缩能力,导致数据膨胀影响查询的性能和磁盘使用率。CU 只支持追加写的方式,也就是说,后面对这个 CU 中的数据做更新或删除都不会真正更改这个 CU,删除是将老数据在字典中标记为作废,更新操作是标记老数据删除后,再写入一条新记录到新 CU,原来的 CU 不会有任何的修改。

从这里我们可以看出,在对列存表进行多次更新 / 删除,或每次只插入很少量的数据后,会导致列存表空间膨胀,大量空间无法有效利用,这是因为列存表在设计上就是为了大批量数据导入以及海量数据按列存储 / 查询。Delta 表正是为了解决这两个问题。在启用 delta 表后,单条或者小批量数据导入时,数据将进入 delta 表中,避免小 CU 的产生,delta 表的增删改查与行存表一致。开启 delta 表后,将显著提升列存表单条导入的性能。

delta 表同样是一张行存表,为了辅助列存表而存在。在创建列存表时系统会为该列存表创建一张对应的 delta 表,delta 表的 oid 可以在 pg_class 中对应列存表元组的 reldeltarelid 属性中查到,所有 delta 表也默认存储在 namespace oid = 100,name 为 cstore 的 namespace 下。

创建一张列存表 col_test,同时设置 reloption 属性 enable_delta=true。在 pg_class 中查看该表对应的 delta 表 oid。

图 7 创建列存表并开启 delta 表

进一步根据该 oid 信息可以查到 delta 表的对应信息。

图 8 查询 delta 表相关信息

可以指定 reloption 选项设置是否为该列存表开启 delta 表:

图 9 开启 / 关闭 delta 表操作


5. 分区表

分区表就是把逻辑上的一张表根据某种方案分成几张物理块进行存储。这张逻辑上的表称之为分区表,物理块称之为分区。分区表是一张逻辑表,不存储数据,数据实际是存储在分区上的。分区表的定义不难理解,下面我们通过一个例子说明分区表的用法。

创建一张有 id 和 name 两个属性的分区表 part_test,该表以 id 的大小进行分区,其中 id<10 的数据存储在分区 location_1,10≤id<20 的数据存储在分区 location_2,所有 id≥20 的数据存储在分区 location_3。

CREATE TABLE part_test(id int,name text) partition BY range(id) (partition locatition_1 values less than (10),partition locatition_2 values less than (20),partition locatition_3 values less than (maxvalue));

创建好 part_test 表后,我们所有的增删改查都是直接对 part_test 表操作的,对用户操作来说 part_test 表与普通表没有什么区别,但实际的存储方式却是严格按照分区的划分方式进行存储的,数据存储在各个分区上,part_test 表作为一张逻辑表不保存数据。我们可以通过 pg_partition 这张系统表查询到一张分区表的分区信息。

图 10 part_test 表分区信息

分区表和分区的关系如图所示:

图 11 分区表和分区关系图


6. 各类表相关对象总结


推荐阅读
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • 本文讨论了Kotlin中扩展函数的一些惯用用法以及其合理性。作者认为在某些情况下,定义扩展函数没有意义,但官方的编码约定支持这种方式。文章还介绍了在类之外定义扩展函数的具体用法,并讨论了避免使用扩展函数的边缘情况。作者提出了对于扩展函数的合理性的质疑,并给出了自己的反驳。最后,文章强调了在编写Kotlin代码时可以自由地使用扩展函数的重要性。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 第四章高阶函数(参数传递、高阶函数、lambda表达式)(python进阶)的讲解和应用
    本文主要讲解了第四章高阶函数(参数传递、高阶函数、lambda表达式)的相关知识,包括函数参数传递机制和赋值机制、引用传递的概念和应用、默认参数的定义和使用等内容。同时介绍了高阶函数和lambda表达式的概念,并给出了一些实例代码进行演示。对于想要进一步提升python编程能力的读者来说,本文将是一个不错的学习资料。 ... [详细]
  • 突破MIUI14限制,自定义胶囊图标、大图标样式,支持任意APP
    本文介绍了如何突破MIUI14的限制,实现自定义胶囊图标和大图标样式,并支持任意APP。需要一定的动手能力和主题设计师账号权限或者会主题pojie。详细步骤包括应用包名获取、素材制作和封包获取等。 ... [详细]
  • 本文介绍了Oracle存储过程的基本语法和写法示例,同时还介绍了已命名的系统异常的产生原因。 ... [详细]
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • 单页面应用 VS 多页面应用的区别和适用场景
    本文主要介绍了单页面应用(SPA)和多页面应用(MPA)的区别和适用场景。单页面应用只有一个主页面,所有内容都包含在主页面中,页面切换快但需要做相关的调优;多页面应用有多个独立的页面,每个页面都要加载相关资源,页面切换慢但适用于对SEO要求较高的应用。文章还提到了两者在资源加载、过渡动画、路由模式和数据传递方面的差异。 ... [详细]
  • HashMap的相关问题及其底层数据结构和操作流程
    本文介绍了关于HashMap的相关问题,包括其底层数据结构、JDK1.7和JDK1.8的差异、红黑树的使用、扩容和树化的条件、退化为链表的情况、索引的计算方法、hashcode和hash()方法的作用、数组容量的选择、Put方法的流程以及并发问题下的操作。文章还提到了扩容死链和数据错乱的问题,并探讨了key的设计要求。对于对Java面试中的HashMap问题感兴趣的读者,本文将为您提供一些有用的技术和经验。 ... [详细]
  • 1Lock与ReadWriteLock1.1LockpublicinterfaceLock{voidlock();voidlockInterruptibl ... [详细]
  • 近期,某用户在重启RAC一个节点的数据库实例时,发现启动速度非常慢。同时业务部门反馈连接RAC存活节点的业务也受影响。通过对日志的分析, ... [详细]
author-avatar
ChoyanaKwok楚楚
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有