共享Detoast

更新时间:
复制 MD 格式

PolarDB PostgreSQL支持共享Detoast(Shared Detoast)功能,能够避免对同一大字段的重复Detoast操作,提升查询执行效率。

功能简介

PostgreSQL使用TOAST(The Oversized-Attribute Storage Technique,超大字段存储技术)机制存储超大字段(如大型JSONB、长文本、大二进制数据等)。当查询需要访问这些字段的实际内容时,需要执行Detoast操作,将分段存储(且可能压缩过)的数据重新组装、解压为完整数据。

原生PostgreSQLDetoast是惰性执行的:每个访问该字段的表达式都会独立执行一次Detoast,彼此之间无法共享结果。例如:

SELECT big_jsonb->'a', big_jsonb->'b', big_jsonb->'c',
       big_jsonb->'d', big_jsonb->'e'
FROM t;

上述查询会对同一行的big_jsonb列重复执行5Detoast,当字段较大时会带来显著的CPU与内存分配开销。

PolarDB PostgreSQL提供共享Detoast功能:同一行数据在执行器中第一次Detoast后,结果会被缓存并在该行的后续表达式求值中直接复用,避免重复Detoast,以少量内存开销换取显著的性能提升。该功能对JIT执行同样生效。

适用范围

支持的PolarDB PostgreSQL的版本如下:

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

说明

您可在控制台查看内核小版本号,也可以通过SHOW polardb_version;语句查看。如未满足内核小版本要求,请升级内核小版本。符合版本条件的集群已默认开启该功能。

适用场景

以下场景可以从共享Detoast功能中获益:

  • 同一大字段被多个表达式访问:如对同一JSONB列提取多个键(WHERE big->>'c3' = '1' AND big->>'c4' = '2'big只需Detoast一次)、对同一长文本列执行多个函数运算等。

  • 输出列表中对同一JSON列输出多个字段:如SELECT big->'a', big->'b', big->'c' FROM t,同一行的big列只需Detoast一次,多个取值表达式直接复用。

  • 大字段同时出现在过滤条件和输出列表中:如WHERE big->>'type' = 'x'SELECT big->'payload'

  • 连接(Join)条件与输出同时引用大字段:支持Nested LoopHash JoinMerge Join等连接节点。

访问次数越多、字段越大,收益越明显。

注意事项与限制

共享Detoast功能存在以下注意事项与限制:

  • 内存开销:共享Detoast功能以内存换时间。缓存Detoast结果会增加单行处理时的内存占用(约为相关字段解压后的大小),但缓存随行处理结束即释放,通常不会造成明显的内存压力。

  • 部分计划节点不启用:当大字段位于SortHashHash Join内表)、MaterializeMemoizeWindowAgg、增量排序等需要物化元组的节点下游时,为避免物化后的元组过大(导致work_mem更快耗尽、产生额外的临时文件I/O),优化器会自动对相关列禁用共享Detoast功能。这是自动行为,无需您手动干预。

  • 仅对被表达式访问的列生效

    • 只有在表达式中被直接运算的TOAST列(如big->'key'length(big_text))才会提前Detoast。

    • 仅作为结果原样输出的列(如SELECT big FROM t)不受影响,仍保持原生惰性行为。

  • 对不涉及大字段的负载有轻微开销:共享Detoast功能会在生成执行计划时额外遍历计划树,并为元组槽维护独立的内存上下文。在完全不涉及TOAST大字段的高频短查询场景(如sysbench OLTP类负载)下,实测有小于3%的性能损耗。若业务以此类负载为主且追求极致性能,可将polar_enable_shared_detoast_datum参数设为OFF,关闭后性能与不含该功能的版本持平。

  • 结果正确性不受影响:共享Detoast功能仅改变Detoast的执行时机与复用方式,不改变任何查询语义与结果。

使用方法

共享Detoast功能由参数polar_enable_shared_detoast_datum控制,在符合版本条件的集群上默认开启,无需任何配置即可使用。

说明

控制台修改polar_enable_shared_detoast_datum参数的能力将在新版本中开放。如果当前控制台中看不到该参数,可以联系技术支持。

参数名称

描述

polar_enable_shared_detoast_datum

用于控制共享Detoast功能的开关,bool类型,取值如下:

  • ON(默认):开启共享Detoast功能。

  • OFF:关闭共享Detoast功能。

功能开启后,优化器会在生成执行计划时自动识别可受益的查询并应用优化,对不适用的场景自动跳过,无需您手动干预。polar_enable_shared_detoast_datum参数在优化器生成执行计划时生效,修改后对新执行的查询(含重新生成计划的预编译语句)生效。

polar_enable_shared_detoast_datum参数支持会话级修改,可在会话内临时关闭或开启,用于对比验证优化效果:

说明

会话级设置仅对当前连接有效,连接断开后恢复默认值。

-- 当前会话内关闭
SET polar_enable_shared_detoast_datum = off;

-- 当前会话内开启
SET polar_enable_shared_detoast_datum = on;

使用示例

  • 构造包含大JSONB字段的测试表,并对同一JSONB列多次取值。同一行的big列只需Detoast一次:

    -- 构造包含大 JSONB 字段的测试表
    CREATE TABLE t_big (id int, big jsonb);
    INSERT INTO t_big
    SELECT i,
           (SELECT jsonb_object_agg(k, repeat('x', 1000))
            FROM generate_series(1, 100) k)
    FROM generate_series(1, 10000) i;
    
    -- 对同一 JSONB 列多次取值
    EXPLAIN ANALYZE
    SELECT big->'1', big->'2', big->'3', big->'5', big->'10'
    FROM t_big;
  • 可通过对比开启/关闭参数时EXPLAIN ANALYZE的执行时间,验证优化效果:

    SET polar_enable_shared_detoast_datum = off;
    EXPLAIN ANALYZE SELECT big->'1', big->'2', big->'3', big->'5', big->'10' FROM t_big;
    
    SET polar_enable_shared_detoast_datum = on;
    EXPLAIN ANALYZE SELECT big->'1', big->'2', big->'3', big->'5', big->'10' FROM t_big;