暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PG13中的功能—B树索引中的重复数据删除

PostgreSQL 13 Beta 1版本于2020年5月21日发布,PostgreSQL 13 Beta 2版本于2020年6月25日发布。虽然Beta 版本中依旧包含一些错误,但是它总是几乎涵盖了完整版本的所有核心功能。PG Beta 版本也是同样如此。PostgreSQL 13 Beta 2版本包括了在正式版中我们所期望的所有重要功能。这其中有一些十分有用且让人激动的功能值得被提及。

主要功能的亮点

如同其他主要的PostgreSQL版本,PG 13版本也旨在提高性能和可用性。一些值得注意的功能有:

1.B树中的重复数据删除

2.增量排序

3.分区表的before行级触发器

4.FETCH FIRST WITH TIES

本文主要关注PG13中引入的b-树索引的重复数据删除,我们对比PG13和PG12来研究这如何影响索引大小和性能
 

B树中的重复项

与一般的看法相反,索引中出现重复项的次数比预期的要多。根据定义,重复条目是B树索引中的叶节点,其中在同一索引中至少有2个索引条目为所有索引列承载相同的数据。
 
重复也以另一种方式发生。当数据库表中的记录被更新时,实际上会创建一个新的元组,旧的元组被标记为删除。在物理或者内存存储中,这个元组现在存储在新的位置,而索引条目同样需要指向新的位置,因此,最终在B树索引中创建了一个新节点。
 

重复数据删除

重复数据删除是一种选择,它将重复的B树索引条目组合到一个组条目中。它避免了重复列数据的需要。TID的排序列表被维持,该列表指向表中的行。维持的TIDs同样服务于唯一的标识一个元组,从而满足了Lehman and Yao 的算法条件之一。B树索引的TIDs是在PG12中引入。
 

重复数据删除是如何工作的

我本以为管理B树是非常简单的,但并非如此。当我们讨论B树索引时,有许多管理各个方面的算法。这使得它成为对于树结构、可用空间管理等内容来说非常复杂的代码。这就是为什么重复数据删除是PG13的一大亮点。
 
有一种假设是当重复数据删除被启用后,我们最后会获得一个没有任何重复项的B树,但并非如此,我们依旧会获得一个有重复项的B树。
 
重复数据删除仅会发生在新的items被插入B树索引的时候,如果索引页中的剩余空闲空间小于新索引元组所需的空间,并且在运行单个索引页vacuum  page compaction之前也是如此。简而言之,当B-Tree索引页分裂时,重复数据删除将在当前索引页上发生,而不是在分裂期间创建的新索引页上发生。然后,将此处的所有重复项组合成列表元组,从而实现重复数据删除。整个过程还确保空间在索引页之间均匀分布。
 

环境设置

现在我们理解了重复数据删除是怎样工作的了,接下来看一下它的实际操作。为了演示它的工作,我们将会比较12.2版本的PG和13Beta 2版本的PG。在两个版本中创建表和B树索引。
    postgres=# CREATE TABLE btree_dups AS (SELECT GENERATE_SERIES(1,
    1000000)::BIGINT AS val);
    SELECT 1000000
    postgres=# CREATE INDEX btree_idx ON btree_dups(val);
    CREATE INDEX
    postgres=# SELECT  c.relname
            , c.relkind        
            , pg_size_pretty( pg_relation_size(c.oid) )
    FROM    pg_class c
    WHERE   c.relname = 'btree_dups'        
    OR  c.oid IN        
    (            
                SELECT i.indexrelid FROM pg_index i WHERE i.indrelid = 
    'btree_dups'::regclass
            );  
      relname   | relkind | pg_size_pretty
    ------------+---------+---------------- 
    btree_dups | r       | 35 MB 
    btree_idx  | i       | 21 MB
    (2 rows)
    在两个版本中初始时的表和索引大小都是相同的,让我们尝试做一些更新的改动。
      postgres=# UPDATE btree_dups SET val = val + 1;
      UPDATE 1000000
      以上两个版本都查询了三次
       

      重复数据删除的实际操作

      现在检查表和索引大小是如何增加的。(简洁起见,跳过SQL语句)
       
      12.2
          relname   | relkind | pg_size_pretty
        ------------+---------+----------------
        btree_dups | r | 104 MB
        btree_idx | i | 86 MB
        (2 rows)
        13 Beta 2
            relname   | relkind | pg_size_pretty
          ------------+---------+----------------
          btree_dups | r | 104 MB
          btree_idx | i | 62 MB
          (2 rows)
          可以看到这是在大小上的重大差异。我们是否要期待读取性能的进一步提高?尽管此文章的范围不包括性能基准测试,但在psql中运行带有定时的简单选择会显示以下结果。
           
          12.2
            postgres=# EXPLAIN SELECT val FROM btree_dups;
            QUERY PLAN
            -------------------------------------------------------------------- 
            Seq Scan on btree_dups  (cost=0.00..23275.00 rows=1000000 width=8)
            (1 row) 

            Time: 2.415 ms
            postgres=# DO
            postgres-# $$BEGIN
            postgres$# PERFORM * FROM btree_dups;
            postgres$# END;
            postgres$# $$;
            DO
            Time: 190.101 ms
            13 Beta 2
              postgres=# EXPLAIN SELECT val FROM btree_dups;
              QUERY PLAN
              -------------------------------------------------------------------- 
              Seq Scan on btree_dups  (cost=0.00..23274.00 rows=1000000 width=8)
              (1 row) 
              Time: 2.221 ms
              postgres=# DO
              postgres-# $$BEGIN
              postgres$# PERFORM * FROM btree_dups;
              postgres$# END;
              postgres$# $$;
              DO
              Time: 174.843 ms
              在多次运行上述select语句后,我获得了中间值。这是一个明显的性能提升,至于具体的大小,则需要一个单独的更加详细的分析。
               

              限制和语法

              在默认情况下,B树索引已经开启了重复数据删除,但是,可以通过为索引存储参数“ deduplicate_items”指定所需的值来将其打开或关闭。关闭索引的重复数据删除不会更改现有的发布列表元组。
               
              但是并非所有B树索引都支持重复数据删除,有一些不受支持的数据类型和容器,以及任何包括禁用重复数据删除的非索引列的索引。
               

              总结

              重复数据删除是一项可以减少磁盘和RAM上的负载并提高性能的主要增强功能,可以避免重复数据会导致索引的膨胀。然而这也会造成性能开销,同时重复数据删除是一个额外的步骤,可能并非总是带来好处。因此,建议明智地使用它,默认情况下保持打开状态,但对于插入频率很高或更新会产生以前不存在的新值的任何索引,请禁用它。

              I Love PG

              PostgreSQLPG2017PostgreSQLPGPostgreSQLPostgreSQL


              技术文章精彩回顾




              PostgreSQL学习的九层宝塔
              PostgreSQL职业发展与学习攻略
              2019,年度数据库舍 PostgreSQL 其谁?
              Postgres是最好的开源软件
              PostgreSQL是世界上最好的数据库
              从Oracle迁移到PostgreSQL的十大理由
              从“非主流”到“潮流”,开源早已值得拥有

              PG活动精彩回顾




              创建PG全球生态!PostgresConf.CN2019大会盛大召开
              首站起航!2019“让PG‘象’前行”上海站成功举行
              走进蓉城丨2019“让PG‘象’前行”成都站成功举行
              中国PG象牙塔计划发布,首批合作高校授牌仪式在天津举行
              群英论道聚北京,共话PostgreSQL
              相聚巴厘岛| PG Conf.Asia 2019  DAY0、DAY1简报
              相知巴厘岛| PG Conf.Asia 2019 DAY2简报
              独家|硅谷Postgres大会简报
              直播回顾 | Bruce Momjian:原生分布式将在PG 14版本发布

              PG培训认证精彩回顾




              中国首批PGCA认证考试圆满结束,203位考生成功获得认证!
              中国第二批PGCA认证考试圆满结束,115位考生喜获认证!
              重要通知:三方共建,中国PostgreSQL认证权威升级!
              近500人参与!首次PGCE中级、第三批次PGCA初级认证考试落幕!
              2020年首批 | 中国PostgreSQL初级认证考试圆满结束
              一分耕耘一分收获,第五批次PostgreSQL认证考试成绩公布

              文章转载自开源软件联盟PostgreSQL分会,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

              评论