编辑:我违反了 SO 的基本规则,我没有回答 OP。由于已经有一个公认的答案,我觉得警告是谨慎的。
通常,混合使用 SQL 和 PL/SQL 是一个非常糟糕的主意。有 2 个独立的代码引擎。有一个 SQL 引擎和一个 PL/SQL 引擎。强制来回切换数千次绝对会降低性能。
我理解程序员为什么要这样做。我得到它。这一切都是封装的、温暖的和模糊的,但它会严重地削弱你。就像大自然一样,它会用它的景象和声音来引诱你,然后它会折断你的脚踝。
甚至像这样愚蠢的事情。
create or replace function my_Date (p_Date in date)
return varchar
as
begin
return to_char(p_Date, 'yyyy/mm/dd');
end;
会杀死你的执行时间。
打开自动跟踪
然后运行这些。
select to_char(created, 'yyyy/mm/dd'), to_char(last_ddl_time, 'yyyy/mm/dd') from all_objects
select my_date(created), my_Date(last_DDL_TIME) From all_objects
第二个需要两倍的时间来运行。我在 1 秒内得到查询 1 和在 2 秒内得到 2 的答案。
这是一个非常简单的案例……我所做的只是转换值。想象一下,如果您必须按照自己的意愿加入它。这真的是最坏的情况。
现在想想当你在函数中隐藏东西时优化器完全无法做的事情。
当你做一个 IN 时,有时作为一个连接做起来要快得多。如果某些条件为真,优化器将为您执行此操作。它会将 IN 转换为 JOIN。但是因为你把select伪装在了一个函数里面,它就不能再判断条件是否成熟了。你已经强迫优化器做一些次优的事情。
优化器依赖的一个关键统计数据是行数。是一行还是十亿。它从表和索引的统计信息中知道。您的功能没有统计信息。
你可以把它们放在那里,可以暗示基数,我不是说你不能,但是为什么呢?你为什么想要?看起来您正在使用该函数,因为您是一个勤奋的程序员,他一生都被告知要将冗余代码分解为函数。
你脑海中的那些规则,几乎没有一个适用于 SQL。优化器不是编译器。它不能内联你的函数。只有您可以帮助您的优化人员获得最佳计划。