如果我将以下函数硬编码到查询中,它的处理速度要快10倍......关于如何使函数快速运行的任何想法?
我认为编写sql函数的一个优点是查询规划器在这些函数上完全正常运行,与PL语言函数形成对比。
顺便说一下,我正在使用PostgreSQL 9.4。
更新
我现在已经意识到执行速度差异不是来自于将查询放在函数中,而是我如何调用函数。
select * from spatial.aggregate_raster_stats_by_geom(155);
>> 1.5秒
select (spatial.aggregate_raster_stats_by_geom(155)).*;
>> 15秒
CREATE OR REPLACE FUNCTION spatial.aggregate_raster_stats_by_geom(
IN arg_rid INTEGER
)
-- This function is called by the trigger that is fired whenever an entry is created in the raster catalog.
RETURNS TABLE(band INTEGER,gid INTEGER, rid INTEGER, product_id INTEGER,ref_datetime TIMESTAMP ,scale INTEGER, count BIGINT, sum FLOAT, mean FLOAT, stddev FLOAT, min FLOAT, max FLOAT) AS
$$
SELECT
band,
gid,
arg_rid as rid,
product_id,
ref_datetime,
scale,
(ST_SummaryStats(clip,band,TRUE)).* -- compute summary statistics (min and max, etc are also in there). TRUE indicates that nodata should be ignored.
FROM
(SELECT
gid,
ST_Union(ST_Clip(rast, geom)) as clip -- assemble the raster tiles and clip them with the assembled polygons
FROM
spatial.raster_tiles AS r
JOIN
spatial.geom_catalog AS polygons
ON ST_Intersects(rast,polygons.geom) -- only select raster tiles that touch the polygons. Spatial indexes should make this fast
JOIN
spatial.geom_metadata AS geometa
ON geometa.product_id = polygons.product_id
WHERE
geometa.aggregate_raster_auto = TRUE
AND r.rid=$1
GROUP by gid
) as foo
cross join (
-- Join bands to the selection
-- this join has to be introduced AFTER the clipping. If done before, then clipping will be performed for each band.
SELECT
generate_series(md.band_data_start,band_count) as band,
data_scale_factor as scale,
md.product_id,
rid,
ref_datetime
FROM spatial.raster_metadata md
JOIN spatial.raster_catalog rst ON rst.product_id = md.product_id
WHERE rst.rid = $1) AS bar2
$$
LANGUAGE sql IMMUTABLE;
答案 0 :(得分:0)
阿。你遗漏了关键细节。
在PostgreSQL中(至少在9.5岁及以上)写作:
SELECT ( f () ).*;
...为每个结果列运行f
一次!
这基本上是一次宏观扩张。
要解决它,请在另一层子查询中进行换行。