Tim*_*ers 9 sql postgresql plpgsql
如果我有以下玩具查询
SELECT *
FROM my_tables
WHERE my_id in (
SELECT my_other_id
FROM my_other_tables
) AND some_slow_func(arg) BETWEEN 1 AND 2;
Run Code Online (Sandbox Code Playgroud)
WHERE子句中的第一个条件是否会短路第二个具有复杂运行时间的条件?
我正在研究一些实际上是plpgsql中FOR LOOP的一部分的sql,我可以对my_other_tables中存在的所有记录进行迭代,然后使用some_slow_func()在FOR LOOP的范围内进行测试.但我很好奇是否支持sql,或者plpgsql支持短路.
一些研究:我查看了Postgres的邮件列表,发现这说SQL一般不支持短路:
http://www.postgresql.org/message-id/171423D4-9229-4D56-B06B-58D29BB50A77@yahoo.com
但其中一个回复表明订单可以通过子选择来强制执行.我不确定他在说什么.我知道子选择是什么,但我不确定如何强制执行命令?有人可以为我澄清一下吗?
如文档所述,WHERE子句中的评估顺序应该是不可预测的.
它与子查询不同.对于当前版本,驱动评估顺序的最简单和常用技术是在CTE中编写子查询.为了确保IN(...)
首先评估,您的代码可以写成:
WITH subquery AS
(select * from my_tables
WHERE my_id in (SELECT my_other_id FROM my_other_tables)
)
SELECT * FROM subquery
WHERE some_slow_func(arg) BETWEEN 1 AND 2;
Run Code Online (Sandbox Code Playgroud)
您可能调整的其他内容是您的函数向优化器发出信号表示它很慢的成本.函数的默认开销是100
,可以使用如下语句更改:
ALTER FUNCTION funcname(argument types) cost N;
Run Code Online (Sandbox Code Playgroud)
N
估算的每次通话费用在哪里,以任意单位表示,应与规划师成本常数进行比较.
我知道这是一个老问题,但最近遇到了类似的问题,并发现在 WHERE 子句中使用 CASE 谓词对我来说效果更好。在上面答案的上下文中:
SELECT *
FROM my_tables
WHERE CASE WHEN my_id in (SELECT my_other_id
FROM my_other_tables)
AND some_slow_func(arg) BETWEEN 1 AND 2
THEN 1
ELSE 0
END = 1;
Run Code Online (Sandbox Code Playgroud)
这使得 SQL 与数据库更加无关。当然,如果您在 my_id 上有索引,它可能不会使用索引,但根据您所处的上下文,这可能是一个不错的选择。