全部产品
Search
文档中心

云原生数据库 PolarDB:预读和预扩展

更新时间:Apr 22, 2024

本文介绍了堆表预读、堆表预扩展以及索引创建预扩展的简介、原理以及使用方法等。

前提条件

支持的PolarDB PostgreSQL版的版本如下:

  • PostgreSQL 14(内核小版本14.5.1.0及以上)

  • PostgreSQL 11(内核小版本1.1.1及以上)

说明

您可通过如下语句查看PolarDB PostgreSQL版的内核小版本的版本号:

  • PostgreSQL 14

    select version();
  • PostgreSQL 11

    show polar_version;

背景信息

PolarDB PostgreSQL版底层使用PolarFS(以下简称为PFS)作为文件系统。不同于 ext4 等单机文件系统,PFS在页扩展过程中,元数据更新开销较大。且PFS的最小页扩展粒度为4 MB。而PostgreSQL 8 KB的页扩展粒度并不适合PFS,将会导致写表或创建索引时性能下降。同时,PFS在读取大块页面时I/O效率更高。

为了适配上述特征,PolarDB PostgreSQL版设计了堆表预读、堆表预扩展、索引创建预扩展的功能,使运行在PFS上的PolarDB PostgreSQL版能够获得更好的性能。

简介

  • 堆表预读

    在PostgreSQL读取堆表的过程中,会以8 KB页为单位通过文件系统读取页面至内存缓冲池(Buffer Pool)中。PFS对于这种数据量较小的I/O操作并不是特别高效。因此,PolarDB PostgreSQL版为了适配PFS而设计了堆表批量预读。

    当读取的页数量大于1时,将会触发批量预读,一次I/O读取128 KB数据至缓冲池中。预读对顺序扫描(Sequential Scan)、Vacuum两种场景性能可以带来一倍左右的提升,在索引创建场景下可以带来18%的性能提升。

  • 堆表预扩展

    在PostgreSQL中,表空间的扩展过程中将会逐个申请并扩展8 KB的页。即使是PostgreSQL支持的批量页扩展,进行一次N页扩展的流程中也包含了N次I/O操作。这种页扩展不符合PFS最小页扩展粒度为4 MB的特性。因此,PolarDB PostgreSQL版设计了堆表批量预扩展。

    在扩展堆表的过程中,一次I/O扩展4 MB页。在写表频繁的场景下(例如装载数据),能够带来一倍的性能提升。

  • 索引创建预扩展

    索引创建预扩展与堆表预扩展的功能类似。索引创建预扩展特别针对PFS优化索引创建过程。在索引创建的页扩展过程中,一次I/O扩展4 MB页。这种设计可以在创建索引的过程中带来30%的性能提升。

    说明

    当前索引创建预扩展只适配了B-Tree索引。其他索引类型暂不支持。

原理介绍

  • 堆表预读

    堆表预读的实现步骤主要分为以下四步:

    1. 在Buffer Pool中申请N个Buffer。

    2. 通过palloc在内存中申请一段大小为N*页大小的空间,简称为p

    3. 通过PFS批量读取堆表中N * 页大小的数据拷贝至p中。

    4. p中N个页的内容逐个拷贝至从Buffer Pool申请的N个Buffer中。

    后续的读取操作会直接命中Buffer。数据流图如下所示:堆表预读

  • 堆表预扩展

    预扩展的实现步骤主要分为以下三步:

    1. 从Buffer Pool中申请N个Buffer,不触发文件系统的页扩展。

    2. 通过PFS的文件写入接口进行批量页扩展,并且写入为全零页。

    3. 对申请出来的页逐个进行页初始化,标识页的可用空间,结束预扩展。

  • 索引创建预扩展

    索引创建预扩展的实现步骤与预扩展类似,但没有涉及Buffer的申请。步骤如下:

    1. 写索引页时,通过PFS的文件写入接口进行批量页扩展,并且写入为全零页。

    2. 将Buffer Pool中已经构建好的索引页写入文件系统中。

使用指南

  • 堆表预读

    堆表预读的参数名为polar_bulk_read_size,功能默认开启,默认大小为128 KB。

    说明

    不建议用户自行修改该参数,128 KB是贴合PFS的最优值,自行调整并不会带来性能的提升。

    • 关闭堆表预读功能。

      ALTER SYSTEM SET polar_bulk_read_size = 0;
      SELECT pg_reload_conf();
    • 开启堆表预读功能并设置预读大小为128 KB。

      ALTER SYSTEM SET polar_bulk_read_size = '128 KB';
      SELECT pg_reload_conf();
  • 堆表预扩展

    堆表预扩展的参数名为polar_bulk_extend_size,功能默认开启,预扩展的大小默认是4 MB。

    说明

    不建议用户自行修改该参数值,4 MB是贴合PFS的最优值。

    • 关闭堆表预扩展功能。

      ALTER SYSTEM SET polar_bulk_extend_size = 0;
      SELECT pg_reload_conf();
    • 开启堆表预扩展功能并设置预扩展大小为4 MB。

      ALTER SYSTEM SET polar_bulk_extend_size = '4 MB';
      SELECT pg_reload_conf();
  • 索引创建预扩展

    索引创建预扩展的参数名为polar_index_create_bulk_extend_size,功能默认开启。索引创建预扩展的大小默认是4 MB。

    说明

    不建议用户自行修改该参数值,4 MB是贴合PFS的最优值。

    • 关闭索引创建预扩展功能。

      ALTER SYSTEM SET polar_index_create_bulk_extend_size = 0;
      SELECT pg_reload_conf();
    • 开启索引创建预扩展功能并设置预扩展大小为4 MB。

      ALTER SYSTEM SET polar_index_create_bulk_extend_size = '4 MB';
      SELECT pg_reload_conf();

性能对比

为了展示堆表预读、堆表预扩展、索引创建预扩展的性能提升效果,在PostgreSQL 14版本的PolarDB PostgreSQL版集群上进行了测试。

  • 规格:8核32 GB内存。

  • 测试场景:400 GB pgbench测试。

  • 堆表预读

    • 400 GB表的Vacuum性能对比如下所示:vacuum性能对比

    • 400 GB表的SeqScan性能对比如下所示:seqscan性能对比

    结论:

    • 堆表预读在Vacuum和SeqScan场景下性能提升了1-2倍。

    • 堆表预读大小在超过默认值128 KB之后对性能提升没有明显帮助。

  • 堆表预扩展

    400 GB表数据装载性能对比如下所示:数据装载性能对比

    结论:

    • 堆表预扩展在数据装载场景下带来一倍的性能提升。

    • 堆表预扩展大小在超过默认值4 MB后对性能没有明显帮助。

  • 索引创建预扩展

    400 GB表创建索引性能对比如下所示:创建索引性能对比

    结论:

    • 索引创建预扩展在索引创建场景下能够带来30%的性能提升。

    • 索引创建预扩展大小超过默认值4 MB对性能没有明显帮助。