Hint是Oracle数据库中很有特色的一个功能,pg和oracle的优化器一样也是CBO(基于成本的)。但是在pg中是没有hint的,但是我们可以去通过设置成本因子,设置优化器开关等方式来"建议"数据库按照我们的想法去生成执行计划,但是并不能强制,例如:
bill=# explain select * from t1;
QUERY PLAN
-------------------------------------------------------
Seq Scan on t1 (cost=0.00..22.70 rows=1270 width=36)
(1 row)
对于上面这个简单的全部扫描查询,即使我们关闭全表扫描开关也没用:
bill=# set enable_seqscan TO off;
SET
bill=# explain select * from t1;
QUERY PLAN
--------------------------------------------------------------------------
Seq Scan on t1 (cost=10000000000.00..10000000022.70 rows=1270 width=36)
(1 row)
那么我们能否在pg中使用像oracle的hint的方法呢?答案是可以的,pg提供了一个pg_hint_plan的插件,可以完成类似的功能。
测试:
下载地址:http://iij.dl.sourceforge.jp/pghintplan/
安装:
pg11@oracle-> tar -zxvf pg_hint_plan11-1.3.4.tar.gz
pg11@oracle-> cd pg_hint_plan11-1.3.4
pg11@oracle-> gmake clean
pg11@oracle-> gmake
pg11@oracle-> gmake install
pg11@oracle-> vi $PGDATA/postgresql.conf
–添加以下内容
shared_preload_libraries = ‘pg_hint_plan’
pg_hint_plan.enable_hint = on
pg_hint_plan.debug_print = on
pg_hint_plan.message_level = log
pg11@oracle-> pg_ctl restart -m fast
使用:
pg11@oracle-> psql bill bill
psql (11.1)
Type "help" for help.
bill=# create extension pg_hint_plan ;
CREATE EXTENSION
用法举例:
bill=# create table a(id int primary key, info text, crt_time timestamp);
CREATE TABLE
bill=# create table b(id int primary key, info text, crt_time timestamp);
CREATE TABLE
bill=# insert into a select generate_series(1,100000), 'a_'||md5(random()::text), clock_timestamp();
INSERT 0 100000
bill=# insert into b select generate_series(1,100000), 'b_'||md5(random()::text), clock_timestamp();
INSERT 0 100000
bill=# analyze a;
ANALYZE
bill=# analyze b;
ANALYZE
bill=# explain select a.*,b.* from a,b where a.id=b.id and a.id<10;
QUERY PLAN
-----------------------------------------------------------------------
Nested Loop (cost=0.58..29.24 rows=9 width=94)
-> Index Scan using a_pkey on a (cost=0.29..3.05 rows=9 width=47)
Index Cond: (id < 10)
-> Index Scan using b_pkey on b (cost=0.29..2.91 rows=1 width=47)
Index Cond: (id = a.id)
(5 rows)
使用pg_hint_plan来改变执行计划 :
bill=# /*+
bill*# HashJoin(a b)
bill*# SeqScan(b)
bill*# */ explain select a.*,b.* from a,b where a.id=b.id and a.id<10;
QUERY PLAN
-----------------------------------------------------------------------------
Hash Join (cost=3.16..2200.67 rows=9 width=94)
Hash Cond: (b.id = a.id)
-> Seq Scan on b (cost=0.00..1935.00 rows=100000 width=47)
-> Hash (cost=3.05..3.05 rows=9 width=47)
-> Index Scan using a_pkey on a (cost=0.29..3.05 rows=9 width=47)
Index Cond: (id < 10)
(6 rows)
更多使用方法举例:
bill=# /*+ SeqScan(a) */ explain select * from a where id<10;
QUERY PLAN
-----------------------------------------------------
Seq Scan on a (cost=0.00..2185.00 rows=9 width=47)
Filter: (id < 10)
(2 rows)
bill=# /*+ BitmapScan(a) */ explain select * from a where id<10;
QUERY PLAN
---------------------------------------------------------------------
Bitmap Heap Scan on a (cost=1.66..13.21 rows=9 width=47)
Recheck Cond: (id < 10)
-> Bitmap Index Scan on a_pkey (cost=0.00..1.66 rows=9 width=0)
Index Cond: (id < 10)
(4 rows)
目前pg_hint_plan支持的hint类型:
http://pghintplan.sourceforge.jp/hint_list.html