Sql 子查询使用函数更快
我在函数中嵌入了一个长查询(~200行):Sql 子查询使用函数更快,sql,postgresql,postgresql-9.3,Sql,Postgresql,Postgresql 9.3,我在函数中嵌入了一个长查询(~200行): CREATE FUNCTION spot_rate(base_currency character(3), contra_currency character(3), pricing_date date) RETURNS numeric(20,8) 无论是直接运行查询还是函数,我都会得到类似的结果和性能。到目前为止还不错 现在我有另一个长查询,它看
CREATE FUNCTION spot_rate(base_currency character(3),
contra_currency character(3),
pricing_date date) RETURNS numeric(20,8)
无论是直接运行查询还是函数,我都会得到类似的结果和性能。到目前为止还不错
现在我有另一个长查询,它看起来像:
SELECT x, sum(y * spot_rates.spot)
FROM (SELECT a, b, sum(c) FROM t1 JOIN t2 etc. (6 joins here)) AS table_1,
(SELECT
currency,
spot_rate(currency, 'USD', current_date) AS "spot"
FROM (SELECT DISTINCT currency FROM table_2) AS "currencies"
) AS "spot_rates"
WHERE
table_1.currency = spot_rates.currency
GROUP BY / ORDER BY
此查询以300毫秒的速度运行,虽然速度很慢,但在这个阶段足够快(考虑到行数和聚合操作,这可能是有意义的)
但是,如果我用等价查询替换即期汇率(货币“USD”,当前日期),它将在5秒以上的时间内运行
无论我使用函数还是等效查询,单独运行子查询都会在大约200毫秒内返回
当用作子查询时,为什么查询比函数运行得慢
ps:我希望有一个通用的答案来解决这个通用的问题-如果没有,我会发布更多的细节,但创建一个人为的例子并不简单
编辑:解释分析在2个子查询和整个查询上运行
- 具有以下功能的子查询:
- 直接查询的子查询:
- 带功能的整体查询:
- 整体查询与直接查询:
- 仅函数体,使用一组参数:
- 尝试将子查询体(相当于函数)移动到CTE中,以保持其完整性。(始终执行CTE,并且查询生成器/计划器从不分解CTE)
- 将部分查询预计算到(TEMP)表或实体化视图中也有助于减少RTE的数量
- 您可以(暂时)增加
,但这将花费更多的计划时间,这当然是有限制的(可能的计划数量随着范围表的大小呈指数增长)join\u collapse\u limit
- 通常,您可以通过错误的查询计划来检测这种行为(比如这里:更少的索引扫描),但是您需要了解模式,并且必须有某种合理的计划(阅读:PK/FK,索引也必须正确)
spot_rate
functionVOLATILE
,稳定的
或不可变的
?@茄子我不认为它们中的任何一个-它是这样声明的:创建或替换函数spot_rate(args)返回数值(20,8)作为$$SELECT xxx$$LANGUAGE SQL代码>您可以使用pgAdmin在对象浏览器中单击函数名并查看SQL窗格中的定义,轻松地检查这一点。无论如何,如果您没有指定任何,PostgreSQL将假定VOLATILE
。如果您将其定义为“稳定”或“不可变”
,那么您的问题的答案很容易猜到,但既然您没有这样做,它看起来确实违反直觉,人们可能会期望相反的结果。您不是第一个问这样的问题的人: