hypopg插件用于幫助您檢查某類索引是否有助于一個或者多個查詢。
前提條件
在使用hypopg插件前,您需要知道:- 需要優化哪些查詢。
- 需要嘗試使用哪些索引類型。
簡介
hypopg插件是PolarDB PostgreSQL版(兼容Oracle)支持的一款開源第三方插件,hypopg創建的虛擬索引不會存在于任何系統表中,而是存放在您連接的私有內存中。由于虛擬索引實際上并不真正存在于任何物理文件中,因此hypopg保證了虛擬索引只會被一個簡單的EXPLAIN語句(不包括ANALYZE選項)使用。虛擬索引并不是真實存在的索引,因此不耗費CPU、磁盤或其他資源。
說明 hypopg插件支持的索引類型如下:
- btree:B-樹索引。
- brin:塊級索引。
- hash:哈希索引。
- bloom:布隆索引(需要先安裝bloom插件)。
使用方法
- 安裝插件。
- 安裝hypopg插件。
CREATE EXTENSION hypopg;
- 查看插件是否已被安裝。
結果如下:\dx hypopg
List of installed extensions Name | Version | Schema | Description --------+---------+--------+------------------------------------- hypopg | 1.3.1 | public | Hypothetical indexes for PostgreSQL (1 row)
說明- 上述結果表示hypopg1.3.1版本已安裝。
- 您也可以通過SQL語句查詢pg_extension表驗證hypopg是否被安裝。示例如下:
結果如下:select * from pg_extension where extname = 'hypopg';
extname | extowner | extnamespace | extrelocatable | extversion | extconfig | extcondition ---------+----------+--------------+----------------+------------+-----------+-------------- hypopg | 10 | 2200 | t | 1.3.1 | | (1 row)
- 安裝hypopg插件。
- 配置參數。
參數 說明 hypopg.enabled 默認值為on。可選參考值如下: - on:啟用hypopg插件。
- off:禁用hypopg插件。說明 當hypopg插件被禁用時,虛擬索引不會被使用,但是已經被創建的虛擬索引不會被刪除。
hypopg.use_real_oids 默認值為off。可選參數值如下: - off:hypopg不會使用真實的對象標識符(oid),而是從空閑范圍中選擇一個標識符。這些標識符由數據庫保留以供在未來版本中使用。由于空閑標識符范圍是在第一次創建使用hypopg時動態計算得到的,且有能夠在備用(Standby)服務器上使用的優勢,因此這樣不會產生任何問題。說明 在默認值為off情況下的缺點是不能同時擁有超過大約2500個的虛擬索引。如果存在的虛擬索引數量超過最大值,那么再創建一個新的虛擬索引的時間將會非常漫長。此時可以調用
hypopg_reset()
函數來解決這個問題,具體使用方法請參見虛擬索引操作方法。 - on:hypopg可以使用真實的對象標識符(oid)。hypopg.use_real_oids可以避免索引超過最大值創建新的虛擬索引時間漫長的問題。hypopg會請求一個真實的標識符,這將需要獲得更多的鎖資源,且不能在備用服務器上使用,但允許使用所有標識符。具體使用方法請參見虛擬索引操作方法。說明 切換該參數狀態不需要重置虛擬索引標識符,真實標識符和非真實標識符可以共存。
- 卸載插件。
DROP EXTENSION hypopg;
說明 更多使用方法,請參見虛擬索引操作方法。
示例測試
- 創建表并插入部分數據,該表上沒有任何索引。示例如下:
檢查索引是否有助于簡單查詢。示例如下:CREATE TABLE hypo (id integer, val text); INSERT INTO hypo SELECT i, 'line ' || i FROM generate_series(1, 100000) i; VACUUM ANALYZE hypo;
結果如下:EXPLAIN SELECT val FROM hypo WHERE id = 1;
QUERY PLAN -------------------------------------------------------- Seq Scan on hypo (cost=0.00..1791.00 rows=1 width=10) Filter: (id = 1) (2 rows)
說明 由于表hypo不存在索引,所以查詢使用的是順序掃描。 - 創建虛擬索引。示例如下:
結果如下:SELECT * FROM hypopg_create_index('CREATE INDEX ON hypo (id)') ;
參數說明如下:indexrelid | indexname ------------+---------------------- 13925 | <13925>btree_hypo_id (1 row)
參數 說明 13925 虛擬索引的標識符。 <13925>btree_hypo_id 生成的虛擬索引名稱。 說明- id列上的簡單B-樹索引有助于此查詢。
- 函數
hypopg_create_index()
將接受任何標準的CREATE INDEX
語句(傳遞給該函數的任何其它語句將被忽略),并為每條語句創建一個虛擬索引。 - 標識符是動態生成的,本示例中為13925。
- 運行EXPLAIN語句查看數據庫是否會使用該索引。示例如下:
結果如下:EXPLAIN SELECT val FROM hypo WHERE id = 1;
QUERY PLAN ------------------------------------------------------------------------------------ Index Scan using "<13925>btree_hypo_id" on hypo (cost=0.04..8.06 rows=1 width=10) Index Cond: (id = 1) (2 rows)
說明 數據庫使用了該類型的索引。 - 運行EXPLAIN語句查看在真正執行語句時數據庫是否會使用虛擬索引。示例如下:
結果如下:EXPLAIN ANALYZE SELECT val FROM hypo WHERE id = 1;
QUERY PLAN --------------------------------------------------------------------------------------------------- Seq Scan on hypo (cost=0.00..1791.00 rows=1 width=10) (actual time=0.030..15.439 rows=1 loops=1) Filter: (id = 1) Rows Removed by Filter: 99999 Planning Time: 0.066 ms Execution Time: 15.492 ms (5 rows)
說明 進一步查看真正執行語句時,數據庫沒有使用虛擬索引。
虛擬索引操作方法
hypopg插件還提供了一些便利的功能和視圖。
- hypopg_list_indexes視圖:列出所有已創建的虛擬索引。示例如下:
結果如下:SELECT * FROM hypopg_list_indexes ;
indexrelid | index_name | schema_name | table_name | am_name ------------+----------------------+-------------+------------+--------- 13925 | <13925>btree_hypo_id | public | hypo | btree (1 row)
- hypopg()函數:以和pg_index相同的格式列出所有已經被創建的虛擬索引。示例如下:
結果如下:SELECT * FROM hypopg() ;
indexname | indexrelid | indrelid | innatts | indisunique | indkey | indcollation | indclass | indoption | indexprs | indpred | amid ----------------------+------------+----------+---------+-------------+--------+--------------+----------+-----------+----------+---------+------ <13925>btree_hypo_id | 13925 | 16450 | 1 | f | 1 | 0 | 1978 | | | | 403 (1 row)
- hypopg_get_indexdef(oid)函數:通過虛擬索引標識符得到實際的CREATE INDEX命令。示例如下:
結果如下:SELECT index_name, hypopg_get_indexdef(indexrelid) FROM hypopg_list_indexes ;
index_name | hypopg_get_indexdef ----------------------+---------------------------------------------- <13925>btree_hypo_id | CREATE INDEX ON public.hypo USING btree (id) (1 row)
- hypopg_relation_size(oid)函數:估計虛擬索引的大小。示例如下:
結果如下:SELECT index_name, pg_size_pretty(hypopg_relation_size(indexrelid)) FROM hypopg_list_indexes ;
index_name | pg_size_pretty ----------------------+---------------- <13925>btree_hypo_id | 2544 kB (1 row)
- hypopg_drop_index(oid)函數:刪除給定標識符的虛擬索引。示例如下:
結果如下:select hypopg_drop_index(13925);
hypopg_drop_index ------------------- t (1 row)
- hypopg_reset()函數:刪除所有虛擬索引。示例如下:
結果如下:select hypopg_reset();
hypopg_reset -------------- (1 row)