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命令,並且不會影響其他會話。