PL/pgSQL是PostgreSQL数据库系统的一个可加载的过程语言。 PL/pgSQL可以用于创建函数和触发器过程,为SQL语言增加控制结构,执行复杂的计算,继承所有用户定义类型、函数、操作符,定义为被服务器信任的语言,而且容易使用。
在PostgreSQL 9.0及其之后的版本中,PL/pgSQL是默认安装的。
本文给出了PL/pgSQL在使用时的一些注意事项和使用建议。
PLpgSQL执行注意事项
1)会话中第一次执行PLpgSQL时,会被编译到抽象语法树(AST)中。而且每次执行时,都会伴随AST执行。
2)会话中第一次执行PLpgSQL时,会进行查询优化。每次执行时,都要进行查询的初始化和执行。
3)PLpgSQL 代码中的每个表达式都是查询。
4)不使用FROM,对应的是简单的表达式,更快的执行速度。
5)使用FROM从句,对应的是完整的查询,速度一般。
6)不要使用ISAM方式,ISAM方式是指索引顺序存取方法。
使用建议
综上所述,使用PLpgSQL时有以下几点建议:
1)尽可能在所有地方都使用简单的表达式。
2)不要使用无意义的查询。
3)不要使用ISAM方式。
4)不要包装查询。
还有一种情况是,由错误的数据类型导致的慢查询,举一个例子:
postgres=# EXPLAIN ANALYZE SELECT * FROM foo where id = 10;
QUERY PLAN
--------------------------------------------------------------------------------
Index Scan using foo_id_key on foo (cost=0.42..8.44 rows=1 width=8) (actual ti
me=0.007..0.008 rows=1 loops=1)
Index Cond: (id = 10)
Planning time: 0.050 ms
Execution time: 0.019 ms
(4 rows)
Time: 0.318 ms
postgres=# EXPLAIN ANALYZE SELECT * FROM foo where id = 10::numeric;
QUERY PLAN
--------------------------------------------------------------------------------
Gather (cost=1000.00..12175.00 rows=5000 width=8) (actual time=0.179..256.782
rows=1 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Parallel Seq Scan on foo (cost=0.00..10675.00 rows=2083 width=8) (actual
time=162.239..247.032 rows=0 loops=3)
Filter: ((id)::numeric = '10'::numeric)
Rows Removed by Filter: 333333
Planning time: 0.080 ms
Execution time: 258.035 ms
(8 rows)
Time: 268.107 ms
这个示例展示了一种我们常犯的错误,即表中定义的id列的数据类型为int,但是变量却被声明为了numeric类型,由于数据类型错误,导致查询速度变慢。
PLpgSQL开发建议
1)不要将代码直接存储到数据库中,而是使用文件或者git的方式完成。
2)部署代码的过程中尽量使用rpm,deb等格式。
3)PLpgSQL开发比较好的工具有:
plpgsql_check
auto_explain
PLpgSQL profiler
pgAdmin(有完整的PLpgSQL debugger)
PLpgSQL使用建议
1)不要使用生命周期短的临时表(除非特别需要使用它),而是使用数组。
2)不要捕获所有的报错。
3)捕获异常不是毫无代价的,同样只在需要的时候这样做。
4)编写测试用例。
5)编写可读性高的代码,PLpgSQL在动态编码方便表现不佳,所以完全可以使用PLPerl, PLPython。
By Kalath