本文为您介绍 hypopg 插件的简介及使用方法。
概述
hypopg 是虚拟索引评估插件,可在不实际创建索引的情况下模拟索引对查询计划的影响,用于评估索引收益、避免无效索引占用存储和拖慢写入。
支持版本
PostgreSQL 版本 | 内核版本 |
PostgreSQL 11 | v11.22_r1.28及以上 |
PostgreSQL 12 | v12.22_r1.31及以上 |
PostgreSQL 13 | v13.22_r1.26及以上 |
PostgreSQL 14 | v14.22_r1.42及以上 |
PostgreSQL 15 | v15.14_r1.27及以上 |
PostgreSQL 16 | v16.10_r1.22及以上 |
PostgreSQL 17 | v17.9_r1.16及以上 |
PostgreSQL 18 | v18.3_r1.6及以上 |
说明:
您可在控制台实例详情页查看当前实例的内核版本,或执行
SHOW tencentdb_version; 查询。插件简介
hypopg 创建的虚拟索引只存在于当前会话中,不写入磁盘、不占用存储、不影响写入性能,仅对当前会话的
EXPLAIN(不含 ANALYZE)生效。通过对比创建虚拟索引前后的执行计划,可判断某索引是否值得真实创建。环境准备
在目标数据库中执行以下语句创建扩展:
postgres=> CREATE EXTENSION hypopg;CREATE EXTENSION
说明:
hypopg 无需预加载,创建后即可使用。
虚拟索引评估流程
1. 查看默认执行计划
以下示例创建测试表,并查看无索引时的执行计划:
postgres=> CREATE TABLE hypo_test(id int, val int);CREATE TABLEpostgres=> INSERT INTO hypo_test SELECT i, i FROM generate_series(1, 10000) AS i;INSERT 0 10000postgres=> ANALYZE hypo_test;ANALYZEpostgres=> EXPLAIN (COSTS OFF) SELECT * FROM hypo_test WHERE val = 5000;QUERY PLAN---------------------Seq Scan on hypo_testFilter: (val = 5000)(2 rows)
无索引时,查询走全表扫描(Seq Scan)。
2. 创建虚拟索引
使用
hypopg_create_index 函数创建虚拟索引,参数为一条 CREATE INDEX 语句:postgres=> SELECT * FROM hypopg_create_index('CREATE INDEX ON hypo_test (val)');indexrelid | indexname------------+---------------------------12821 | <12821>btree_hypo_test_val(1 row)
返回虚拟索引的 OID 和名称(名称由系统生成)。
3. 查看执行计划变化
再次执行
EXPLAIN,观察虚拟索引对计划的影响:postgres=> EXPLAIN (COSTS OFF) SELECT * FROM hypo_test WHERE val = 5000;QUERY PLAN-----------------------------------------------------------Index Scan using "<12821>btree_hypo_test_val" on hypo_testIndex Cond: (val = 5000)(2 rows)
执行计划由全表扫描变为索引扫描,说明该索引对查询有效,值得真实创建。
4. 验证虚拟索引不占真实存储
postgres=> SELECT count(*) AS real_indexes FROM pg_indexes WHERE tablename = 'hypo_test';real_indexes--------------0(1 row)
系统目录中没有任何真实索引,虚拟索引不占用存储。
管理虚拟索引
查看虚拟索引列表
postgres=> SELECT * FROM hypopg_list_indexes;indexrelid | index_name | schema_name | table_name | am_name------------+---------------------------+-------------+------------+---------12821 | <12821>btree_hypo_test_val | public | hypo_test | btree(1 row)
查看虚拟索引定义
postgres=> SELECT hypopg_get_indexdef(indexrelid) FROM hypopg_list_indexes;hypopg_get_indexdef---------------------------------------------CREATE INDEX ON public.hypo_test USING btree (val)(1 row)
删除单个虚拟索引
postgres=> SELECT hypopg_drop_index((SELECT indexrelid FROM hypopg_list_indexes LIMIT 1));hypopg_drop_index-------------------t(1 row)
清空全部虚拟索引
postgres=> SELECT hypopg_reset();hypopg_reset--------------(1 row)
参数说明
参数 | 默认值 | 说明 |
hypopg.enabled | on | 是否启用 hypopg,设为 off 后虚拟索引不再影响 EXPLAIN |
hypopg.use_real_oids | off | 是否使用真实 OID(默认使用伪 OID 区间,备库也可使用) |
常见问题
Q:虚拟索引会影响其他会话或真实数据吗?
A:不会。虚拟索引仅存在于创建它的会话中,断开连接即自动消失,不写入磁盘、不影响其他会话和写入性能。
Q:为什么 EXPLAIN ANALYZE 看不到虚拟索引的效果?
A:虚拟索引仅对
EXPLAIN(不含 ANALYZE)生效。EXPLAIN ANALYZE 会真实执行查询,无法使用不存在的虚拟索引。Q:如何验证多个候选索引?
A:可在同一会话中多次调用
hypopg_create_index 创建多个虚拟索引,用 hypopg_list_indexes 查看列表,配合 EXPLAIN 逐一或组合评估,评估完成后用 hypopg_reset 清空。