1. 简介

HypoPG是一个可以创建“虚拟/虚假”索引的插件,让你不用建立真实的索引,就可以让你事先判断出在一些字段上建索引是否有效的插件。

通常加索引是一个比较有效的优化方法,但是对于一些复杂的SQL,在表上加索引有没有效果是难以很快判断的,需要更多的一些知识,如需要了解数据分布、输入条件、列的唯一值等等情况来判断,而使用HypoPG则不需要这么复杂的判断了,通过HypoPG创建虚拟索引,然后看复杂SQL的执行计划就可以判断出建索引是否有效了。所以对于没有DBA的公司这个插件可以帮助开发人员快速确定是否该加索引,对于有DBA的公司也可以节省DBA的时间。

HypoPG的源代码放在github上:

官方文档:

我们下面就会详细演示HypoPG的使用。

2. 安装HypoPG

如果你的PostgreSQL是使用yum安装的官方的PostgreSQL版本,则可以直接用yum安装HypoPG这个插件:

  1. yum install hypopg

如果从源码安装,则:

先使用git把源码从github上拉下来:

  1. git clone https://github.com/dalibo/hypopg.git

查看版本标签:

  1. [root@pg01 hypopg]# git tag
  2. 0.0.1
  3. 0.0.2
  4. 0.0.3
  5. 0.0.4
  6. 0.0.5
  7. 1.0.0
  8. 1.1.0

选择一个版本,通常选择最新版本,这里选择1.1.0:

  1. git checkout 1.1.0

然后编译安装即可:

  1. make
  2. make install

3. 使用

在数据库创建插件:

  1. CREATE EXTENSION hypopg;

建测试表:

  1. postgres=# CREATE TABLE hypotest AS SELECT seq as id, ('osdba ' || seq)::text as t FROM generate_series(1,100000) as seq;
  2. SELECT 100000

查看没有索引时全表扫描的代价:

  1. postgres=# explain select * from hypotest where id=1228;
  2. QUERY PLAN
  3. ------------------------------------------------------------
  4. Seq Scan on hypotest (cost=0.00..1791.00 rows=1 width=15)
  5. Filter: (id = 1228)
  6. (2 rows)

建虚拟索引:

  1. postgres=# \timing
  2. Timing is on.
  3. postgres=# SELECT hypopg_create_index('CREATE INDEX ON hypotest (id)');
  4. hypopg_create_index
  5. ----------------------------------
  6. (16635,<16635>btree_hypotest_id)
  7. (1 row)
  8. Time: 0.446 ms
  9. postgres=#

因为虚拟索引是一个假的,建立时即不占用CPU,也会实际占用磁盘空间,故从上面可以看到很快就把虚拟索引建好了。

这时我们再用explain来查看执行计划:

  1. postgres=# EXPLAIN SELECT * FROM hypotest WHERE id = 1228;
  2. QUERY PLAN
  3. ------------------------------------------------------------------------------------------
  4. Index Scan using <16635>btree_hypotest_id on hypotest (cost=0.04..8.06 rows=1 width=15)
  5. Index Cond: (id = 1228)
  6. (2 rows)
  7. Time: 0.350 ms

发现执行计划变成了走索引:

  • Index Scan using <16635>btree_hypotest_id on hypotest (cost=0.04..8.06 rows=1 width=15)

如果我们真实执行此条SQL(在explain中加analyze):

  1. postgres=# EXPLAIN ANALYZE SELECT * FROM hypotest WHERE id = 1228;
  2. QUERY PLAN
  3. ------------------------------------------------------------------------------------------------------
  4. Seq Scan on hypotest (cost=0.00..1791.00 rows=1 width=15) (actual time=0.145..6.661 rows=1 loops=1)
  5. Filter: (id = 1228)
  6. Rows Removed by Filter: 99999
  7. Planning time: 0.037 ms
  8. Execution time: 6.684 ms
  9. (5 rows)
  10. Time: 7.021 ms

从上面可以看到真实的执行还是走全表扫描的执行计划,这就是HypoPG的作用,HypoPG的虚拟索引只是影响非真实执行的explain的结果,而不会改变SQL执行时的真实执行计划。

HypgPG还提供了一些函数用于查看、删除虚拟索引等操作:

查看有哪些虚拟索引:

  1. postgres=# SELECT * FROM hypopg_list_indexes();
  2. indexrelid | indexname | nspname | relname | amname
  3. ------------+--------------------------+---------+----------+--------
  4. 16635 | <16635>btree_hypotest_id | public | hypotest | btree
  5. (1 row)
  6. Time: 3.310 ms

估算此真正建立后会有多大:

  1. postgres=# SELECT indexname, pg_size_pretty(hypopg_relation_size(indexrelid)) FROM hypopg_list_indexes();
  2. indexname | pg_size_pretty
  3. --------------------------+----------------
  4. <16636>btree_hypotest_id | 2544 kB
  5. (1 row)
  6. Time: 1.029 ms

获得建索引的DDL语句:

  1. postgres=# select hypopg_get_indexdef(16636);
  2. hypopg_get_indexdef
  3. --------------------------------------------------
  4. CREATE INDEX ON public.hypotest USING btree (id)
  5. (1 row)
  6. Time: 0.294 ms

删除虚拟索引:

  1. postgres=# select hypopg_drop_index(16635);
  2. hypopg_drop_index
  3. -------------------
  4. t
  5. (1 row)
  6. Time: 0.409 ms
  7. postgres=# SELECT * FROM hypopg_list_indexes();
  8. indexrelid | indexname | nspname | relname | amname
  9. ------------+-----------+---------+---------+--------
  10. (0 rows)
  11. Time: 0.601 ms

也可以调用hypopg_reset()函数把所有的虚拟索引都删除掉:

  1. postgres=# select hypopg_reset();
  2. hypopg_reset
  3. --------------
  4. (1 row)
0 评论  
添加一条新评论