JIT编译主要可以让长时间运行的CPU密集型的查询受益。对于短查询,执行JIT编译增加的开销常常比它节省的时间还要多。
为了判断是否应该使用JIT编译,会用到一个查询的总的估计代价(见第 75 章和第 20.7.2 节)。查询的估计代价将与jit_above_cost的设置进行比较。如果代价更高,JIT编译将被执行。然后需要两个进一步的决定。首先,如果估计代价超过jit_inline_above_cost的设置,该查询中使用的短函数和操作符都将被内联。其次,如果估计代价超过jit_optimize_above_cost的设置,会应用昂贵的优化来改进产生的代码。这些选项中的每一种都会增加JIT编译的开销,但是可以可观地降低查询执行时间。
这些基于代价的决定将在规划时做出,而不是在执行时做出。这意味着,在使用预备语句并且使用了一个一般性的计划时(见PREPARE),配置参数的值实际上是在预备时控制这些决定,而不是由执行时的设置来决定。
如果jit被设置为off
或者没有JIT实现可用(例如因为服务器没有用--with-llvm
编译),即便基于上述原则能带来很大的好处,JIT也不会被执行。把jit设置成off
对规划时和执行时都有影响。
EXPLAIN可以被用来看看是否使用了JIT。例如,这是一个没有使用JIT的查询:
=# EXPLAIN ANALYZE SELECT SUM(relpages) FROM pg_class; QUERY PLAN ------------------------------------------------------------------------------------------------------------- Aggregate (cost=16.27..16.29 rows=1 width=8) (actual time=0.303..0.303 rows=1 loops=1) -> Seq Scan on pg_class (cost=0.00..15.42 rows=342 width=4) (actual time=0.017..0.111 rows=356 loops=1) Planning Time: 0.116 ms Execution Time: 0.365 ms (4 rows)
看看给出的计划代价,不使用JIT是非常合理的,JIT的代价会比可能得到的节省更高。调整代价限制会导致用到JIT:
=# SET jit_above_cost = 10; SET =# EXPLAIN ANALYZE SELECT SUM(relpages) FROM pg_class; QUERY PLAN ------------------------------------------------------------------------------------------------------------- Aggregate (cost=16.27..16.29 rows=1 width=8) (actual time=6.049..6.049 rows=1 loops=1) -> Seq Scan on pg_class (cost=0.00..15.42 rows=342 width=4) (actual time=0.019..0.052 rows=356 loops=1) Planning Time: 0.133 ms JIT: Functions: 3 Options: Inlining false, Optimization false, Expressions true, Deforming true Timing: Generation 1.259 ms, Inlining 0.000 ms, Optimization 0.797 ms, Emission 5.048 ms, Total 7.104 ms Execution Time: 7.416 ms
如这里所看到的,JIT被用到了,但是内联和昂贵的优化没有被用到。如果jit_inline_above_cost或者jit_optimize_above_cost也被降低,这种情况会被改变。