在连续列上加入多列与单连接的条件?

时间:2015-04-29 19:39:14

标签: sql oracle join dbvisualizer

我观察到有两种方法可以在多个表上实现目标。将更新结果集中的列,并且可能需要速度。结果集可通过以下方式获得:

案例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;

OR

案例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;

两者都给出相同的结果,只有连接条件变化。哪个会更快/更快地运行?

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,开发人员)和数据库中实现通用吗?这取决于数据类型还是串联总是很昂贵?我实际上并不需要连接的结果。感谢。

3 个答案:

答案 0 :(得分:3)

我认为连接版本实际上总是比较慢。

如果您单独比较的任何列都有索引,则数据库通常可以使用索引来优化连接。比较连接时,它必须执行全表扫描,因为计算结果不会出现在索引中。

即使列未编制索引,数据库仍可以更有效地执行比较。它一次比较一对列,并且只要其中一个比较失败就可以停止。使用连接时,必须首先组合两行中的所有列,然后进行字符串比较。

最后,如果任何列都是数字,则连接将需要将数字转换为字符串的附加步骤。

答案 1 :(得分:3)

很简单,加入各个列是正确的。连接到连接值是不正确的。与任何性能讨论分开,你应该编写正确的代码。

对于任何特定查询,您可以使用串联编写最正确的查询。但是,当您获得您不期望的数据时,您几乎肯定会引入一些会让您感到困惑的细微错误。在这种情况下,只要您的列包含句点,就有可能错误地匹配数据('a.b' || '.' || null = 'a' || '.' || 'b.')。在其他情况下,您还会遇到其他细微问题 - 日期和数字可能会使用可能产生不同结果的不同会话级设置隐式转换为字符串(您的NLS_DATE_FORMAT可能包含时间组件,或者可能包含时间组件不是这样你的连接值可能包括也可能不包括时间的比较。如果您经常连接列,那么根据表中的数据和执行代码的用户,您将会遇到大量具有非常微小错误的查询。从维护和支持的角度来看,这很可怕。性能最多应该是次要问题。

从性能角度来看,正确的连接几乎肯定会超越连接方法。在您正确加入时生成查询计划时,优化器将能够考虑作为连接一部分的各个列的正常索引。如果您要连接值,那么Oracle最好能够对正常索引进行全面扫描,以获取需要连接在一起的所有数据。但这可能效率低得多(特别是当你的行数超过几千行时)。

理论上,连接方法在某些地方对某些查询更有效吗?当然。虐待开发者可能会在连接结果上创建基于函数的索引,避免在各列上创建索引,并生成连接方法更有效的测试用例。但是,通过在基本列上创建适当的相应索引(或多个索引),可以很容易地解决这个问题。是否有可能连接对某些查询更有效,因为它阻止优化器使用它本来想要使用的索引?当然。但这几乎可以肯定地表明,您应该解决优化器设置或统计数据问题,而不是在问题上使用创可贴。

答案 2 :(得分:0)

这取决于表上的索引。通常,索引是使用列列表定义的,但不是列的串联(作为表达式),因此根据经验,第二个版本通常像索引一样更快。

那就是说,dba可能(无论出于何种原因,可能是醉酒或精神错乱)决定在列的连接上创建一个索引。在这种情况下,语句的第一个版本可以使用索引而第二个版本不能。