微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

PostgreSQL函数的运行速度比直接查询慢

如何解决PostgreSQL函数的运行速度比直接查询慢

当我尝试将一个简单的sql语句包装为一个函数时,我的问题就开始了。该请求花了几毫秒完成,开始花费数秒。 我在google上可以阅读所有内容,但这全都与使用函数参数有关。 然后我摆脱了参数,但这并不能解决问题。

所以,现在我有以下sql语句

select fn_tz(idata.system_timestamp),gp.zname,fc.*
from jv idata   
join gp on st_distance(waypoint,geom)=0
join fc ON 
    idata.fare_code = fc.fare_code  AND 
    fc.validity @> fn_tz(idata.system_timestamp)::date  and 
    fc.polygon_name = gp.name
where idata.item_id='21159704983720122917';

当我直接运行此查询时,大约需要80毫秒才能执行。但是,如果我将未经修改的相同查询放在函数主体中,则大约需要10秒钟!

无论如何,我已经尝试了所有想到的事情

  1. 常规PLPGsql函数return query ...
  2. 常规sql函数select ...
  3. 具有动态SQL查询return query execute 'select ...')的PLPGsql函数
  4. 终于我尝试了准备/执行语句

以上所有方法给出的结果相同-10秒。

然后我在准备好的语句上运行EXPLAIN ANALYZE EXECUTE ...,但是即使从它的输出中,我也无法理解为什么它运行10秒

Hash Join  (cost=75.05..962862.24 rows=110 width=8) (actual time=1.075..10290.527 rows=476091 loops=1)
  Hash Cond: ((idata.fare_code = fc.fare_code) AND (gp.name = (fc.polygon_name)::text))
  Join Filter: (fc.validity @> (fn_tz(idata.system_timestamp))::date)
  ->  nested Loop  (cost=0.00..925098.69 rows=59399 width=54) (actual time=0.298..8300.070 rows=53922 loops=1)
        Join Filter: (st_distance(idata.waypoint,gp.geom) = '0'::double precision)
        Rows Removed by Join Filter: 2212398
        ->  Seq Scan on jv idata  (cost=0.00..4402.99 rows=53999 width=54) (actual time=0.039..33.038 rows=53960 loops=1)
              Filter: (item_id = '21159704983720122917'::text)
              Rows Removed by Filter: 3079
        ->  Materialize  (cost=0.00..13.30 rows=220 width=64) (actual time=0.000..0.003 rows=42 loops=53960)
              ->  Seq Scan on gp  (cost=0.00..12.20 rows=220 width=64) (actual time=0.006..0.025 rows=42 loops=1)
  ->  Hash  (cost=40.22..40.22 rows=2322 width=16) (actual time=0.717..0.717 rows=2268 loops=1)
        Buckets: 4096  Batches: 1  Memory Usage: 141kB
        ->  Seq Scan on fc  (cost=0.00..40.22 rows=2322 width=16) (actual time=0.008..0.332 rows=2322 loops=1)
Planning Time: 0.008 ms
Execution Time: 10324.558 ms

令人惊讶的是,如果我在原始查询上运行EXPLAIN ANALYZE,它也将花费大约10秒钟的时间,并产生几乎相同的执行计划。

我的服务器-Google Cloud Platform上Postgres 11.8的托管实例

我还能做什么/尝试?

更新: 似乎我需要强调-我没有在寻找改善查询性能方法。直接查询运行80毫秒,对此我感到满意。 我想找到原因-为什么直接查询函数主体快 100次(!)

解决方法

fn_tz可能会降低性能2秒钟左右,但是主要问题是您使用的是st_distance而不是st_dwithin,可以通过索引来支持它:

select fn_tz(idata.system_timestamp),gp.zname,fc.*
from jv idata   
join gp on st_dwithin(waypoint,geom,0)
join fc ON 
    idata.fare_code = fc.fare_code  AND 
    fc.validity @> fn_tz(idata.system_timestamp)::date  and 
    fc.polygon_name = gp.name
where idata.item_id='21159704983720122917';

索引将是:

CREATE INDEX ON jv USING gist (waypoint);

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。