PostgreSQL物理存储_第1页
PostgreSQL物理存储_第2页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、PostgreSQL物理存储介绍我最初是为自己写这篇文章的,我想对底层物理存储有足够的了解,以便能够掌握可能影响数据库的其他概念。这篇文章可能更多的是针对有类似兴趣的人,我会尽量保持准确,但目的是让它更容易理解,所以我可能会忽略一些细节。您应该了解Postgres如何处理物理存储吗?也许不是,但是如果您需要调查一些问题,了解它是如何工作的是很有用的。PostgreSQL有一个关于这个主题的章节,但就我个人而言,我不得不投入额外的资源来理解它。我发现很难浏览文档的多个部分和外部资源,所以这是我在一篇文章中收集基本信息的尝试。在这篇文章中,我没有费心重写所有内容,所以在某些地方我重用了官方文档中的

2、段落。在本文撰写时,Postgres的当前版本是9.5,这篇文章中的信息可能在将来的版本中被废弃。为了演示本文的例子,我们假设有一个名为foo的数据库,其中包含一个名为bar的表。一旦你深入到有关存储的文档中,你就会遇到一些不太常见的术语,比如关系、元组、堆、块、页让我来解释一下它们的意思:元组(tuple)或项(item)是行的同义词;关系(relation)是表的同乂词;文件节点(filenode)是表示对表或索引的引用的id;块(block)和页(page)是相等的,它们表示存储表的文件的8kb段信息;堆(heap)是指堆文件(heapfile)。堆文件是大小可变的无序记录列表。虽然共享

3、相似的名称,但是堆文件与堆数据结构不同;XID:事务ID,也是32位的量。在长时间运转的数据库里,它也可能会重叠。重叠后数据库就有可能出错,所以需要采取措施解决。只要我们采取一些合适的维护步骤,这并不是很要命的问题。比如我们定义做vaccum。或者手动重置;CTID表示行数据在其表中的物理位置。CTID也是每个表都可以使用的特殊列,但除非特别提到,否则不可见。它由页码(物理块号)和项标识符的索引(物理行号)组成;OID代表对象标识符;Y数据库集群(databasecluster),我们称数据库集群为磁盘上的存储区域。数据库集群是由运行中的数据库服务器的单个实例管理的数据库集合;资料移除(VAC

4、CUM),PostgreSQL数据库需要定期维护,称为资料移除。如果您在本文的其余部分中遇到了这个术语,请不要感到惊讶。在可能的情况下,我在少数地方简化了内容。我的数据库存储在哪里数据库集群使用的数据文件一起存储在集群的数据目录中,通常称为PGDATA在可用于定义它的环境变量名称之后)。根据您的操作系统或安装,PGDATA可以有不同的位置。对于集群中的每个数据库,PGDATA/base中都有一个子目录,以pg_database中数据库的OID命名。这个子目录是数据库文件的默认位置。如果希望列出集群中每个数据库的OID,可以运行以下查询。selectoid,datnamefrompg_datab

5、ase;oid|datname+1|template112398|template012403|postgres17447|foo如果您正在寻找一个特定数据库的OID,那么您可以在查询中添加一个WHERE子句:selectoid,datnamefrompg_databaseWHEREdatname='foo'另一种查找数据库OID的方法是使用命令行oid2name。它是一个实用程序,用于检查PostgreSQL使用的文件结构,以获得关于如何使用它的更多信息$>oid2nameAlldatabases:OidDatabaseNameTablespac/p>

6、foopg_defaulttemplate0pg_defaulttemplate1pg_default上面的OID在您的系统中可能完全不同,但是现在我们知道,与数据库foo有关的所有文件都存储在PGDATA/base/17447中。如果您问自己,作为pg_database的表存储在哪个数据库中,那么它们不是在PGDATA/base中,而是在PGDATA/globaI中。现在,我们知道在文件系统中何处可以找到数据库,所以让我们尝试找出在何处可以找到表。存储表的地方每个表都存储在一个单独的文件中。对于普通关系,这些文件是以表或索引的文件名命名的,可以在表pg_class的列relfilenode中

7、找到。pg_class是存在于pg_catalog模式中的系统表。当一个表超过1gb时,它被分成GB大小的段。第一个段的文件名与文件名相同随后的段被命名为filenode.1,filenode.2,等等。这种安排避免了在有文件大小限制的平台上出现问题。表的文件名通常与其OID匹配,但情况不一定如此。要查找表文件名路径,可以在连接到数据库时运行以下查询:selectpg_relation_filepath('bar');pg_relation_filepathbase/17447/27741如果您不想要路径,而只想要文件名,那么您可以使用具有相同参数的函数pg_relation_

8、filenode。对于数据库OID,可以使用oid2name找到表的文件名>oid2name-dfoo-tbarFromdatabase"foo":FilenodeTableName27741bar系统表在前一节中,我们讨论了一些关于系统表的内容,很有趣的是,我们知道有一个系统目录模式,其中包含您可能想要查询的表,以查找额外信息。创建数据库时,除了公共模式和用户创建的模式外,每个数据库还包含一个pg_catalog模式,该模式包含系统表和所有内置数据类型、函数和操作符。pg_catalog始终是搜索路径的有效部分,因此在查询系统表时不需要使用前缀。一旦通过psql连接

9、到您的数据库,您可以通过以下方式列出系统表:dtpg_catalog.*如何存储行每个表都存储为固定大小(通常为8Kb)的页面数组。在表中,所有页面在逻辑上是等价的,因此可以在任何页面中存储特定的项(行)。用于存储表的结构是堆文件。堆文件是大小可变的无序记录列表。堆文件的结构是一组页面(或块),每个页面包含一组项。术语item指的是存储在页面上的一行。页面结构如下:ItemnTupleTupleSpecialPageHeaderTuple它包含了一些标题,我们不打算涵盖,但他们提供了有关校验和的信息,开始的自由空间,结束的自由空间,标头后面的项是一个数组标识符,由指向实际项的(偏移量、长度)对

10、组成。由于在释放项标识符之前不会移动项标识符,因此可以长期使用它的索引来引用项,即使在将项本身在页面上移动以压缩空闲空间时也是如此。指向项的指针称为CTID(ItemPointer),由PostgreSQL创建,它由页码和项标识符的索引组成。项目本身存储在从未分配空间的末尾向后分配的空间中。总之,在页面中,指向行的指针存储在开始处,元组(行)存储在页面的末尾。您可以通过在选定的列中添加CTID来访问一行的CTID:SELECTctid,*frombar;有哪些限制根据AboutPostgreSQL,根据列类型的不同,列的最大数量在250到1600之间。列类型会影响它,因为在PostgreSQL

11、行中可能最多有8kb(个页面)宽,它们不能跨页面.这并不意味着列的值被限制为8kb。列中有较大的值是可能的,这取决于类型,因为PostgreSQL有一个称为TOAST的机制可以处理这个问题。您可以容纳多少列仍然是有限制的,这取决于使用的数据类型的宽度。即使是指向TOAST属性的指针也需要一些字节。超大属性存储技术在前一节中,我们已经说过,如果某些列的类型是TOAST-able,那么它们的大小可以超过页面的大小。让我们对TOAST做一个概述。首先,TOAST代表超大属性存储技术,这可能是计算机科学史上最好的缩写。PostgreSQL使用固定的页面大小(通常为8kB),并且不允许元组跨多个页面。因

12、此,不可能直接存储非常大的字段值。当试图存储超过这个大小的行时,TOAST基本上将大列的数据分解成更小的“块”,并将它们存储到TOAST表中。您创建的每个表都有自己关联的吐司表(惟一的),根据您插入的行大小,最终可能会使用吐司表,也可能不会使用吐司表。所有这些对用户都是透明的,默认情况下是启用的。该机制是通过将大列条目拆分为2KB字节并将它们作为块存储在TOAST表中来实现的。然后,它存储长度和指向TOAST条目的指针,该条目位于列通常存储的位置。由于指针系统是如何实现的,大多数TOAST'able列类型都被限制在1GB的最大大小。与更直接的方法(比如允许行值跨页)相比,TOAST有许

13、多优点。只有在将结果集发送到客户机时,才会提取(如果选择了)toast属性的大值。与没有任何脱机存储(TOAST)的情况相比,表本身要小得多,而且它的行更多地适合共享缓冲区缓存。排序集也更有可能变小,这意味着排序完全在内存中完成。在我们的示例中,OID为27741的表bar将包含TOAST表pg_toast_27741。关于吐司还有更多要说的,它也提供压缩,但我保持它的本质。TOAST使它对用户透明,但要记住,TOAST-able列有1GB的限制。您可以在1GB中存储大量数据,对数组类型中的数据进行反规格化或将文档存储在JSONB类型中非常有用。自由空间映射每个表都有一个空闲空间映射,它存储关

14、系中可用的空闲空间的信息。空闲空间映射存储在文件名加上后缀_fsm的文件中。存储在空闲空间映射中的值并不精确。它们四舍五入到页面大小(32字节,默认为8kb)的1/256的精度,并且在插入和更新元组时没有完全保持最新。有些操作将更新freespace映射,删除所有行,但是VACCUM将更新freespace映射,以便将来的行能够知道它们适合哪个页面。由于一行的更新或删除不会立即删除该行的旧版本,所以通过运行VACUUM更新freespace映射。为了获得多版本并发控制(MVCC)的好处,这种方法是必要的:当行版本仍然对其他事务可见时,不能删除它。但最终,任何事务都不再对过时或删除的行版本感兴趣

15、。然后必须回收它所占用的空间,以便新行重用,以避免磁盘空间需求的无限制增长。真空的标准形式删除表中的死行版本,并标记出可供将来重用的空间。但是,它不会将空间返回给操作系统,除非在特殊情况下,表末尾的一个或多个页面完全空闲,并且可以获得一个独占表锁。这并不意味着页面内的空闲空间是碎片化的,真空重写整个块,有效地打包剩余的行,并在页面中留下一个连续的空闲空间块。相反,VACUUMFULL通过编写一个没有死空间的表文件的完整新版本来主动压缩表。这将最小化表的大小,但可能需要很长时间。它还需要额外的磁盘空间来保存表的新副本,直到操作完成。常规真空的目的是避免需要真空充满。其思想不是保持表的最小大小,而

16、是保持磁盘空间的稳定使用:每个表占用的空间等于它的最小大小加上两次吸尘之间占用的空间。在过去,当VACUUM运行时,它必须查看表中的每个元组,因为没有关于自上次VACUUM以来哪些页面可能没有更新的信息。PostgreSQL引入了可视性映射,VACUUM现在可以执行表数据的部分扫描,跳过标记为完全可见的页面。局部扫描意味着对真空进行更少的I/O操作。您可以通过以下查询查询表中页面可用的空闲空间:CREATEEXTENSIONpg_freespace;SELECT*FROMpg_freespace('bar':regclass);可视图每个表还有一个可见性映射(VM),用于跟踪哪

17、些页面只包含已知对所有活动事务可见的元组。换句话说,跟踪已知没有死行的页面。可视性映射与表文件一起存储在一个单独的文件中,以关系的文件名和_vm后缀命名。例如,关系栏的文件名是27741,VM存储在一个名为12345_vm的文件中,与主关系文件位于同一个目录中。我们在前一节中已经看到,死行是由于MVCC机制造成的。可见性映射只是为每个堆页面存储一个位。setbit表示页面上的所有元组对所有事务都是可见的。这意味着该页面不包含任何需要空化的元组。从某种意义上说,映射是保守的,因为我们要确保,无论何时设置了一个位,我们都知道条件为真,但是如果没有设置一个位,那么它可能为真,也可能不为真。可见性映射位仅由vacuum设置,但通过页面上的任何数据修改操作清除。索引是什么索引也作为文件存储在与表相同的目录中。索引是另一个故事,我没有涵盖他们,因为它会使这篇文章更长。即使索引也有页面,它们也遵循不同的结构,因为它们是b-tree(默认情况下)。想要使用Postgres从事具有挑战性的项目吗?如果你对与Postgres合作一些有趣的项目感兴趣,请到Opend

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论