PostgreSQL插件HypoPG:支持虚拟索引

本文涉及的产品
云原生数据库 PolarDB PostgreSQL 版,企业版 4核16GB
推荐场景:
HTAP混合负载
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
简介: PostgreSQL插件HypoPG:支持虚拟索引

通过索引可以加速查询。但是执行SQL时,并不是所有索引都会使用。如果花费很长时间创建一个索引,最后却用不到,岂不是又浪费时间又浪费磁盘空间。那有没有啥方法,可以即不浪费时间又不浪费空间,提前知道这个索引能否可用?HypoPG插件可以帮助创建一个虚拟索引,即不耗费CPU也不耗费磁盘


轻量级实现:HypoPG


HypoPG作为扩展插件,可拔插,支持PG9.2及其以上版本,无需重新启动服务即可使用。每个后端都有自己的一组虚拟索引,并不会干扰其他连接。另外,虚拟索引存储在内存中,添加/删除大量索引并不会使系统目录膨胀。该插件实现的限制:必须通过用户自定义函数来完成。


使用方法


使用时,需要CREATE EXTENSION hypopg;来加载插件。虚拟索引属于独立后台进程,因此并发时,不同进程的虚拟索引并不会彼此影响。下面是也给例子:

    rjuju=# CREATE TABLE hypo AS SELECT id, 'line ' || id AS val FROM generate_series(1,10000) id;
    rjuju=# EXPLAIN SELECT * FROM hypo WHERE id = 1;
                          QUERY PLAN
    -------------------------------------------------------
     Seq Scan on hypo  (cost=0.00..180.00 rows=1 width=13)
       Filter: (id = 1)
    (2 rows)

    创建虚拟索引最简单的方法:使用hypopg_create_index带有CREATE INDEX语句作为参数的函数:


    rjuju=# SELECT * FROM hypopg_create_index('CREATE INDEX ON hypo (id)');

    注意,CREATE INDEX语句中某些信息会被忽略,例如索引名。一些被忽略的信息会在未来版本中处理。也可以在自己的后端查看可用的虚拟索引:

      rjuju=# SELECT * FROM hypopg_list_indexes ;
      indexrelid |                 indexname                 | nspname | relname | amname
      -----------+-------------------------------------------+---------+---------+--------
      205101     | <41072>btree_hypo_id                      | public  | hypo    | btree

      如果需要有关虚拟索引更多信息,hypopg()函数将以类似于pg_index系统目录的方式返回虚拟索引。限制看下之前的EXPLAIN语句是否会使用这样的索引:

        rjuju=# EXPLAIN SELECT * FROM hypo WHERE id = 1;
                                             QUERY PLAN
        ------------------------------------------------------------------------------------
         Index Scan using <41072>hypo_btree_hypo_id on hypo  (cost=0.29..8.30 rows=1 width=13)
           Index Cond: (id = 1)
        (2 rows)

        当然,加上ANALYZE后就不会使用了

          rjuju=# EXPLAIN ANALYZE SELECT * FROM hypo WHERE id = 1;
                                                     QUERY PLAN
          -------------------------------------------------------------------------------------------------
           Seq Scan on hypo  (cost=0.00..180.00 rows=1 width=13) (actual time=0.036..6.072 rows=1 loops=1)
             Filter: (id = 1)
             Rows Removed by Filter: 9999
           Planning time: 0.109 ms
           Execution time: 6.113 ms
          (5 rows)

          使用hypopg_drop_index(indexrelid)函数将虚拟索引删除,或者关闭当前连接。该插件还提供了隐藏和恢复某个索引的功能:1)先用hypopg_reset()清除其他索引之前的影响:SELECT hypopg_reset();2)创建2个虚拟索引,并执行EXPLAIN

            rjuju=# CREATE INDEX ON hypo(id);
            rjuju=# CREATE INDEX ON hypo(id, val);
            rjuju=# EXPLAIN SELECT * FROM hypo WHERE id = 1;
                                                QUERY PLAN
            ----------------------------------------------------------------------------------
            Index Only Scan using hypo_id_val_idx on hypo  (cost=0.29..8.30 rows=1 width=13)
              Index Cond: (id = 1)
            (2 rows)

            3)查询计划使用hypo_id_val_idx索引,使用hypopg_hide_index(oid)隐藏其中一个索引:

              rjuju=# SELECT hypopg_hide_index('hypo_id_val_idx'::REGCLASS);
              rjuju=# EXPLAIN SELECT * FROM hypo WHERE id = 1;
              QUERY PLAN
              -------------------------------------------------------------------------
              Index Scan using hypo_id_idx on hypo (cost=0.29..8.30 rows=1 width=13)
                Index Cond: (id = 1)
              (2 rows)

              4)查询计划使用了另一个索引hypo_id_idx。使用hypopg_hide_index(oid)再把它隐藏掉:

                rjuju=# SELECT hypopg_hide_index('hypo_id_idx'::REGCLASS);
                rjuju=# EXPLAIN SELECT * FROM hypo WHERE id = 1;
                QUERY PLAN
                -------------------------------------------------------
                Seq Scan on hypo (cost=0.00..180.00 rows=1 width=13)
                  Filter: (id = 1)
                (2 rows)

                查询计划又退回使用SeqScan了。5)使用hypopg_unhide_index(oid)恢复索引:


                rjuju=# SELECT hypopg_unhide_index('hypo_id_idx'::regclass);
                rjuju=# EXPLAIN SELECT * FROM hypo WHERE id = 1;
                QUERY PLAN
                -------------------------------------------------------------------------
                Index Scan using hypo_id_idx on hypo (cost=0.29..8.30 rows=1 width=13)
                  Index Cond: (id = 1)
                (2 rows)

                6)可以使用函数hypopg_hidden_indexes()或者视图hypopg_hidden_indexes查看隐藏了哪些索引:


                rjuju=# SELECT * FROM hypopg_hidden_indexes();
                indexid
                ---------
                526604
                526603
                12659
                (3 rows)

                  rjuju=# SELECT * FROM hypopg_hidden_indexes;
                   indexrelid |      index_name      | schema_name | table_name | am_name | is_hypo
                  ------------+----------------------+-------------+------------+---------+---------
                        12659 | <12659>btree_hypo_id | public      | hypo       | btree   | t
                       526603 | hypo_id_idx          | public      | hypo       | btree   | f
                       526604 | hypo_id_val_idx      | public      | hypo       | btree   | f
                  (3 rows)

                  7)可以使用函数hypopg_unhide_all_indexes()恢复所有隐藏的虚拟索引。请注意,隐藏现有索引的功能仅适用于当前会话中的EXPLAIN 命令,不会影响其他会话。


                  参考


                  https://rjuju.github.io/postgresql/2015/07/02/how-about-hypothetical-indexes.htmlhttps://github.com/HypoPG/hypopghttps://hypopg.readthedocs.io/en/rel1_stable/

                  相关实践学习
                  使用PolarDB和ECS搭建门户网站
                  本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
                  阿里云数据库产品家族及特性
                  阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
                  目录
                  相关文章
                  |
                  2月前
                  |
                  XML 关系型数据库 数据库
                  使用mybatis-generator插件生成postgresql数据库model、mapper、xml
                  使用mybatis-generator插件生成postgresql数据库model、mapper、xml
                  142 0
                  |
                  3月前
                  |
                  人工智能 自然语言处理 关系型数据库
                  |
                  3月前
                  |
                  SQL JSON 关系型数据库
                  [UE虚幻引擎插件DTPostgreSQL] PostgreSQL Connector 使用蓝图连接操作 PostgreSQL 数据库说明
                  本插件主要是支持在UE蓝图中连接和操作PostgreSQL 数据库。
                  45 2
                  |
                  10月前
                  |
                  SQL 关系型数据库 Go
                  《增强你的PostgreSQL:最佳扩展和插件推荐》
                  《增强你的PostgreSQL:最佳扩展和插件推荐》
                  723 0
                  |
                  3月前
                  |
                  关系型数据库 数据库 PostgreSQL
                  Docker【应用 03】给Docker部署的PostgreSQL数据库安装PostGIS插件(安装流程及问题说明)
                  Docker【应用 03】给Docker部署的PostgreSQL数据库安装PostGIS插件(安装流程及问题说明)
                  260 0
                  |
                  3月前
                  |
                  关系型数据库 数据库 PostgreSQL
                  PostgreSQL【应用 01】使用Vector插件实现向量相似度查询(Docker部署的PostgreSQL安装pgvector插件说明)和Milvus向量库对比
                  PostgreSQL【应用 01】使用Vector插件实现向量相似度查询(Docker部署的PostgreSQL安装pgvector插件说明)和Milvus向量库对比
                  354 1
                  |
                  3月前
                  |
                  SQL 监控 关系型数据库
                  postgresql|数据库|插件学习(二)---postgresql-12的外置插件pg_profile的启用和使用
                  postgresql|数据库|插件学习(二)---postgresql-12的外置插件pg_profile的启用和使用
                  159 0
                  |
                  3月前
                  |
                  SQL 监控 关系型数据库
                  postgresql|数据库|插件学习(一)---postgresql-12的内置插件pg_stat_statements的启用和使用
                  postgresql|数据库|插件学习(一)---postgresql-12的内置插件pg_stat_statements的启用和使用
                  123 0
                  |
                  SQL 存储 自然语言处理
                  玩转阿里云RDS PostgreSQL数据库通过pg_jieba插件进行分词
                  在当今社交媒体的时代,人们通过各种平台分享自己的生活、观点和情感。然而,对于平台管理员和品牌经营者来说,了解用户的情感和意见变得至关重要。为了帮助他们更好地了解用户的情感倾向,我们可以使用PostgreSQL中的pg_jieba插件对这些发帖进行分词和情感分析,来构建一个社交媒体情感分析系统,系统将根据用户的发帖内容,自动判断其情感倾向是积极、消极还是中性,并将结果存储在数据库中。
                  玩转阿里云RDS PostgreSQL数据库通过pg_jieba插件进行分词
                  |
                  11月前
                  |
                  存储 关系型数据库 数据库
                  PostgreSQL技术大讲堂 - 第28讲:索引内部结构
                  从零开始学PostgreSQL技术大讲堂 - 第28讲:索引内部结构
                  574 2