我观察到有两种方法可以在多个表上实现一个目标。结果集中的一列将被更新,速度可能是一个要求。结果集可通过以下方式获得:
案例1:
select ert.*
from eval_rep_track ert
inner join
(
select erp.evaluation_fk, erp.report_type, LTRIM(erp.assign_group_id, '/site/') course_name
from eval_report_dup@prod erp
inner join eval_report er
on er.id = erp.id
where erp.status='queue'
and er.status='done'
) cat
on ert.eval_id || '.' || ert.report_type || '.' || ert.course_name = cat.evaluation_fk || '.' || cat.report_type || '.' || cat.course_name;
或
案例2:
select ert.*
from eval_rep_track ert
inner join
(
select erp.evaluation_fk, erp.report_type, LTRIM(erp.assign_group_id, '/site/') course_name
from eval_report_dup@prod erp
inner join eval_report er
on er.id = erp.id
where erp.status='queue'
and er.status='done'
) cat
on ert.eval_id = cat.evaluation_fk
and ert.report_type = cat.report_type
and ert.course_name = cat.course_name;
两者给出相同的结果,只是连接条件不同。哪个会运行/exec更快?
eval_id为NUMBER
,report_type和course_name为VARCHAR2
。
根据所使用的开发人员,案例1具有以下统计信息:[SELECT-3077行,0.048秒]获取的结果集…执行了1条语句,影响了3077行,执行/获取时间:0.048/0.236秒[1成功,0警告,0错误]
而情况2:[SELECT-3077行,0.019秒]已提取结果集…执行了1条语句,影响了3077行,执行/获取时间:0.019/0.194秒[1成功,0警告,0错误]
结果表明,情况2更快。这会在任何平台(ide、开发人员)和数据库中通用吗?这取决于数据类型还是串联总是很昂贵?我实际上并不需要串联的结果。谢谢
我认为使用串联的版本实际上总是会更慢。
如果您单独比较的任何列都有索引,则数据库通常能够使用这些索引来优化联接。当您比较串联时,它必须执行完整的表扫描,因为计算结果不会在索引中。
即使列没有索引,数据库仍然可以更有效地执行比较。它一次比较一对列,一旦其中一个比较失败,它就可以停止。当使用串联时,它必须首先组合两行中的所有列,然后进行字符串比较。
最后,如果任何一列是数字列,则串联将需要额外的步骤将数字转换为字符串。
很简单,在各个列上连接是正确的。连接到连接的值不正确。与任何关于性能的讨论分开,您应该编写正确的代码。
对于任何特定的查询,您都可以使用串联编写一个基本正确的查询。但几乎可以肯定的是,当你得到意想不到的数据时,你会引入一些微妙的错误。在这种情况下,一旦列包含句点,就有可能不正确地匹配数据('a.b' || '.' || null = 'a' || '.' || 'b.'
)。在其他情况下,您会遇到其他微妙的问题——日期和数字可能会使用不同的会话级别设置隐式转换为字符串,这可能会产生不同的结果(您的NLS_DATE_FORMAT
可能包含时间组件,也可能不包含,因此您的连接值可能包含也可能不包括时间比较)。如果您通常连接列,那么最终会出现许多查询,这些查询基于表中的数据和执行代码的用户,具有非常微妙的错误。从维护和支持的角度来看,这太可怕了。性能至多应该是次要问题。
从性能的角度来看,正确的联接几乎肯定会优于串联方法。当您正确地联接时,优化器将能够在生成查询计划时考虑联接中各个列的正常索引。如果要连接值,Oracle最多可以对正常索引进行完全扫描,以获得需要连接在一起的所有数据。但这可能效率要低得多(尤其是当您的行数超过几千行时)。
从理论上讲,串联方法对某个地方的查询是否更有效率?当然虐待狂开发人员可能会在连接的结果上创建基于函数的索引,避免在各个列上创建索引,并生成连接方法更有效的测试用例。然而,通过在基本列上创建适当的相应索引(或多个索引),可以很容易地弥补这一点。连接是否可能对某些查询更有效,因为它阻止优化器使用它想要使用的索引?当然但这几乎可以肯定地表明,您在优化器设置或统计数据方面存在问题,应该解决这些问题,而不是在问题上使用创可贴。
它取决于表上的索引。通常,索引是用列列表定义的,但不是用列的串联(作为一个表达式)定义的,因此根据经验,第二个版本的索引速度比通常更快。
也就是说,dba可能(出于任何原因,可能是醉酒或精神错乱)决定在列的串联上创建索引。在这种情况下,语句的第一个版本可以使用索引,而第二个版本则不能。