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

PostgreSQL的数据存储(十二)数据存储

4.3.2Tuple是否可以跨页面PostgreSQLusesafixedpagesize(commonly8kB),anddoesnotallowtuplestospanmult

4.3.2 Tuple是否可以跨页面

PostgreSQL uses a fixed page size (commonly 8 kB), and does not allow tuples to span multiple pages. Therefore, it is not possible to store very large field values directly. To overcome this limitation, large field values are compressed and/or broken up into multiple physical rows. This happens transparently to the user, with only small impact on most of the backend code. The technique is affectionately known as TOAST (or “the best thing since sliced bread”).

【翻译】PostgreSQL使用固定页面大小(通常是8字节),并且不允许元组跨越多个页面。因此,直接存储非常大的值是不可能的。为了克服这一限制,大字段值进行压缩和/或分成多个物理行。这对用户透明,对大多数后端代码只有小的影响。该技术是亲切地称为TOAST(或“有史以来最好的事情”)。

以上英文是PG帮助系统给出的描述,中文是简单翻译。对于数据库系统来说,这是处理大数据的最好的方式吗?

回到本节标题提出的问题,元组是否可以跨页面?答案是:PG存储的基本单位是tuple(元组,或称为记录),一条完整的tuple是不可以跨页面分开存储的。

4.3.3 微对象存储方式

一个tuple,可能由多种数据类型的“列”组成,有的列可能有空值,有的列可能是定长的,有的列可能是变长的。

列数据信息,要存储在物理存储设备,使用时要被读入内存,即内外存要交换数据,如何交换更为合适?

有个概念叫做“内存对齐”,是否有外存对齐?为什么要内存对齐?

PG处理元组,涉及读和写。

读数据块到buf,从buf变为数据页(pg知道数据页的格式,所以才能分解数据页上的信息);数据页上存在元组tuple,读出每个tuple,才能得知具体的数据;每个tuple的格式,也在tuple上标明,这样,才能识别tuple中的具体列的信息。这一步,是靠函数完成的。

写数据内容到buf,是先形成tuple(heap_form_tuple->heap_fill_tuple),然后把tuple写到buf,由系统在某个时刻,把脏的buf写到外存。

但是,如何形成tuple呢?不同数据类型的列,在创建表的时候,就已经把列存储相关的信息,写到了系统表(pg_attribute)中,在读取元组中的内容时,要根据系统表存储的信息,进行逐列读取。

PG规定了不同数据类型如何存储,基本原则一:如果是值存储,直接存储值;如果是引用存储,则先存放一个指针,指针指向真正数据所在的位置。可以用PG联机帮助中的话佐证:

typbyval determines whether internal routines pass a value of this type by value or by reference. typbyval had better be false if typlen is not 1, 2, or 4 (or 8 on machines where Datum is 8 bytes). Variable-length types are always passed by reference. Note that typbyval can be false even if the length would allow pass-by-value

PG存储数据类型基本原则二:如果是变长类型,则按变长方式处理,区分了一个页面存储不下的情况(toast方式)、较段的变长类型、以及其他等(查看heap_fill_tuple函数[1])。PG联机帮助中的话:

For a fixed-size type, typlen is the number of bytes in the internal representation of the type. But for a variable-length type, typlen is negative. -1 indicates a “varlena” type (one that has a length word), -2 indicates a null-terminated C string.

PG存储数据类型基本原则三:对于字符串的处理(上段中为“-2”的情况)。

另外,其他情况的处理,如下:

typalign is the alignment required when storing a value of this type. It applies to storage on disk as well as most representations of the value inside PostgreSQL. When multiple values are stored consecutively, such as in the representation of a complete row on disk, padding is inserted before a datum of this type so that it begins on the specified boundary. The alignment reference is the beginning of the first datum in the sequence.

Possible values are:

c = char alignment, i.e., no alignment needed.

s = short alignment (2 bytes on most machines).

i = int alignment (4 bytes on most machines).

d = double alignment (8 bytes on many machines, but by no means all).

Note

For types used in system tables, it is critical that the size and alignment defined in pg_type agree with the way that the compiler will lay out the column in a structure representing a table row.

这段话是在说,不同类型的存储,是要求有对齐格式的,对齐,是内存中便于操作数据的一种指令加速方式。外存存储的数据,同内存中的格式一致,这样,就不用把外存读入的数据进行转换,存储时,也不用特意从内存格式转换为外存(非对齐)格式,加快了操作的效率,但牺牲了外存的存储空间。



[1] 查看heap_fill_tuple函数,可以清晰了解不同数据类型的存储细节






推荐阅读
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文介绍了Oracle存储过程的基本语法和写法示例,同时还介绍了已命名的系统异常的产生原因。 ... [详细]
  • 本文介绍了为什么要使用多进程处理TCP服务端,多进程的好处包括可靠性高和处理大量数据时速度快。然而,多进程不能共享进程空间,因此有一些变量不能共享。文章还提供了使用多进程实现TCP服务端的代码,并对代码进行了详细注释。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • Java实战之电影在线观看系统的实现
    本文介绍了Java实战之电影在线观看系统的实现过程。首先对项目进行了简述,然后展示了系统的效果图。接着介绍了系统的核心代码,包括后台用户管理控制器、电影管理控制器和前台电影控制器。最后对项目的环境配置和使用的技术进行了说明,包括JSP、Spring、SpringMVC、MyBatis、html、css、JavaScript、JQuery、Ajax、layui和maven等。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • c语言\n不换行,c语言printf不换行
    本文目录一览:1、C语言不换行输入2、c语言的 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 本文介绍了游标的使用方法,并以一个水果供应商数据库为例进行了说明。首先创建了一个名为fruits的表,包含了水果的id、供应商id、名称和价格等字段。然后使用游标查询了水果的名称和价格,并将结果输出。最后对游标进行了关闭操作。通过本文可以了解到游标在数据库操作中的应用。 ... [详细]
  • LVS实现负载均衡的原理LVS负载均衡负载均衡集群是LoadBalance集群。是一种将网络上的访问流量分布于各个节点,以降低服务器压力,更好的向客户端 ... [详细]
author-avatar
百变精灵110
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有