HYPOPG是一种后Ql扩展,增加了对假设索引的支持。
一个假设的(或虚拟)索引是一个索引,它实际上并不存在,因此不会花费CPU,磁盘或任何资源来创建。它们有用,因为您可以知道PostgreSQL是否会使用这些索引,而无需花费资源来创建这些索引。
有关更多信息,请咨询官方文件。
有关其他一般信息,您也可以咨询此博客文章。
sudo make installCREATE EXTENSION hypopg; 请注意,HypOPG不提供扩展升级脚本,因为在创建的任何对象中都没有保存的数据。因此,您需要首先删除扩展名,然后再次创建它以获取新版本。
注意:假设索引包含在单个后端中。因此,如果您添加多个假设索引,则可以EXPLAIN并发联系不会被您的假设索引所困扰。
假设一个简单的测试案例:
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语句(如arg)一起使用。
例如:
rjuju=# SELECT * FROM hypopg_create_index('CREATE INDEX ON hypo (id)');
注意: CREATE INDEX语句中的一些信息将被忽略,例如提供的索引名称。一些忽略的信息将在以后的版本中处理。
您可以在您自己的后端检查可用的假设索引:
rjuju=# SELECT * FROM hypopg_list_indexes ;
indexrelid | index_name | schema_name | table_name | am_name
------------+-------------------------------+-------------+------------+---------
50573 | <50573>btree_hypo_id | public | hypo | btree
如果您要使用的CREATE INDEX命令也需要引用,则建议使用美元引用语法。例如:
rjuju=# SELECT * FROM hypopg_create_index($$CREATE INDEX ON hypo (id) WHERE val = 'line 1'$$);
如果您需要有关假设索引的更多技术信息,则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 EXPLAIN才能使用假设索引:
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_list_indexes视图返回并调用hypopg_reset()一次删除hypopg_drop_index(indexrelid) ,或者只需关闭当前连接。
继续使用上述情况,您可以hide existing indexes ,但应使用hypopg_reset()首先清除其他索引的先前效果。
创建两个真正的索引并运行EXPLAIN :
rjuju=# SELECT hypopg_reset();
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)
查询计划使用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)
查询计划现在使用其他索引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)
现在查询计划更改为Seq Scan 。使用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)
当然,您还可以隐藏假设索引:
rjuju=# SELECT hypopg_create_index('CREATE INDEX ON hypo(id)');
rjuju=# EXPLAIN SELECT * FROM hypo WHERE id = 1;
QUERY PLAN
------------------------------------------------------------------------------------
Index Scan using "<12659>btree_hypo_id" on hypo (cost=0.04..8.05 rows=1 width=13)
Index Cond: (id = 1)
(2 rows)
rjuju=# SELECT hypopg_hide_index(12659);
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_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)
要恢复所有现有索引,您可以使用功能hypopg_unhide_all_indexes() 。请注意,隐藏现有索引的功能仅适用于当前会话中的dixply命令,并且不会影响其他会话。