2016-12-26 54 views
3

我试图解释,让我为难,性能问题选择...JOIN性能与在一个循环中

我有2个表,A和B.

表A定义的对象:

+----+--------------+ 
+ ID + other_things + 
+----+--------------+ 
+ 1 + ~~~~~~~~~~~~ + 
+ 2 + ~~~~~~~~~~~~ + 
+ 3 + ~~~~~~~~~~~~ + 
+----+--------------+ 

此表中有575行。

表B定义了所述对象的一些属性。

+----+-------------+-------------+ 
+ ID + prop_type + prop_value + 
+----+-------------+-------------+ 
+ 1 + prop1 + foo  + 
+----+-------------+-------------+ 
+ 1 + prop2 + toto  + 
+----+-------------+-------------+ 
+ 3 + prop2 + lorem  + 
+----+-------------+-------------+ 

此表中有20254行。

的目的是让所有的“PROP2”值的表A中的项目

有些用户已经在这里种足以帮助我建立了“良好”的解决方案(见问答。41331902 ):

SELECT A.ID, B.prop_value 
FROM A LEFT JOIN 
    B 
    ON A.ID = B.ID AND B.prop_type = 'prop2'; 

该查询在大约20秒内执行。

然而,目前使用的其他版本,我试图改善开头:

FOR (
SELECT ID as id_a FROM A 
) 
DO 
prop = (select prop_value from B where prop_type = 'prop2' and id = id_a); 
write id_a || ' ' || prop; 
END 

这给了相同的结果,但查询在1.5秒内完成......

这是我从我在网上阅读的理解比JOIN应该是更好的一个循环,但实际结果说不然...

我试图改变表的顺序(即大连接小),但只会让事情变得更糟(最多1分钟E)。

你能帮我理解这里会发生什么吗?

附注:我不能得到执行计划,因为数据库引擎不允许它(AspenTech的的SQLPlus)

非常感谢您的帮助

+0

糟糕。我将所有变量重新命名以保持一般性,其中一些已经被中断。 – Maxime

+0

您的循环代码等同于内部连接,并且您将性能与编码为外部连接的查询进行性能比较,但由于您的where子句而实际上是内部连接。将第一个查询作为显式内部联接运行,并将其用于比较。 –

+0

@DanBracuk我不明白你的意思。如果我在第一个查询中用'INNER JOIN'替换我的'LEFT JOIN',我得不到相同的结果,即表A中的表B中没有'表'中的'prop2'的项。 对不起,新手评论... – Maxime

回答

2

如果你有这个疑问:

SELECT A.ID, B.prop_value 
FROM A LEFT JOIN 
    B 
    ON A.ID = B.ID AND B.prop_type = 'prop2'; 

而且要加快步伐,创建B索引:

CREATE INDEX idx_b_id_type_value ON B(id, prop_type, prop_value); 

这应该会大大提高性能。

如果B有一个索引,其中prop_type是索引中的第一个键,那么您的双查询版本会更快。我应该补充一点:我没有Aspen SQL的经验。另一种可能性是它只有一个糟糕的优化器。

+0

是我的一个错误,我删除了太多。有一个'哪里'的条件来获得相同的结果。 – Maxime