PostgreSQL插件HypoPG:支持虚拟索引

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
简介: 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数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
                  目录
                  相关文章
                  |
                  18小时前
                  |
                  关系型数据库 分布式数据库 数据库
                  PolarDB常见问题之加了索引但是查询没有使用如何解决
                  PolarDB是阿里云推出的下一代关系型数据库,具有高性能、高可用性和弹性伸缩能力,适用于大规模数据处理场景。本汇总囊括了PolarDB使用中用户可能遭遇的一系列常见问题及解答,旨在为数据库管理员和开发者提供全面的问题指导,确保数据库平稳运行和优化使用体验。
                  |
                  18小时前
                  |
                  存储 关系型数据库 分布式数据库
                  数据库索引回表困难?揭秘PolarDB存储引擎优化技术
                  PolarDB分布式版存储引擎采用CSM方案均衡资源开销与可用性。
                  数据库索引回表困难?揭秘PolarDB存储引擎优化技术
                  |
                  18小时前
                  |
                  SQL JSON 关系型数据库
                  [UE虚幻引擎插件DTPostgreSQL] PostgreSQL Connector 使用蓝图连接操作 PostgreSQL 数据库说明
                  本插件主要是支持在UE蓝图中连接和操作PostgreSQL 数据库。
                  18 2
                  |
                  18小时前
                  |
                  SQL 关系型数据库 分布式数据库
                  数据库索引,一文揭秘PolarDB XPlan索引选择
                  深度解读PolarDB分布式版XPlan的索引选择
                  数据库索引,一文揭秘PolarDB XPlan索引选择
                  |
                  7月前
                  |
                  SQL 关系型数据库 Go
                  《增强你的PostgreSQL:最佳扩展和插件推荐》
                  《增强你的PostgreSQL:最佳扩展和插件推荐》
                  473 0
                  |
                  18小时前
                  |
                  SQL 算法 关系型数据库
                  PolarDB-X的XPlan索引选择
                  对于数据库来说,正确的选择索引是基本的要求,选错索引轻则导致查询缓慢,重则导致数据库整体不可用。PolarDB-X存在多种不同的索引,局部索引、全局索引、列存索引、归档表索引。本文主要介绍一种CN上的局部索引算法:XPlan索引选择。
                  125774 13
                  PolarDB-X的XPlan索引选择
                  |
                  18小时前
                  |
                  关系型数据库 定位技术 索引
                  在关系型数据库中,常见的索引种类包括哪些
                  在关系型数据库中,常见的索引种类包括哪些
                  493 0
                  |
                  18小时前
                  |
                  关系型数据库 数据库 PostgreSQL
                  PostgreSQL【应用 01】使用Vector插件实现向量相似度查询(Docker部署的PostgreSQL安装pgvector插件说明)和Milvus向量库对比
                  PostgreSQL【应用 01】使用Vector插件实现向量相似度查询(Docker部署的PostgreSQL安装pgvector插件说明)和Milvus向量库对比
                  214 1
                  |
                  18小时前
                  |
                  关系型数据库 数据库 PostgreSQL
                  Docker【应用 03】给Docker部署的PostgreSQL数据库安装PostGIS插件(安装流程及问题说明)
                  Docker【应用 03】给Docker部署的PostgreSQL数据库安装PostGIS插件(安装流程及问题说明)
                  167 0
                  |
                  18小时前
                  |
                  SQL 监控 关系型数据库
                  postgresql|数据库|插件学习(二)---postgresql-12的外置插件pg_profile的启用和使用
                  postgresql|数据库|插件学习(二)---postgresql-12的外置插件pg_profile的启用和使用
                  83 0