【问题标题】:JOIN performance vs. select in a loopJOIN 性能与循环选择
【发布时间】:2016-12-26 14:50:34
【问题描述】:

我试图解释一个令我困惑的性能问题...

我有两张桌子,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 行。

目的是获取表 A 中项目的所有 'prop2' 值。

这里的一些用户非常友好地帮助我设置了“好的”解决方案(请参阅 q. 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 分钟)。

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

旁注:我无法获得执行计划,因为数据库引擎不允许它(AspenTech 的 SQLPlus)

非常感谢您的帮助

【问题讨论】:

  • 糟糕。我重命名了所有变量以保持其通用性,其中一些已在中间删除。
  • 您的循环代码等效于内部联接,并且您正在将性能与编码为外部联接但由于您的 where 子句而实际上是内部联接的查询进行比较。将您的第一个查询作为显式内部连接运行并使用它进行比较。
  • @DanBracuk 我不明白你的意思。如果我在第一个查询中将我的“LEFT JOIN”替换为“INNER JOIN”,我不会得到相同的结果,即表 A 中的项目在表 B 中没有“prop2”。对不起新手的言论......

标签: sql sqlplus aspen


【解决方案1】:

如果您有此查询:

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 的经验。另一种可能性是它只有一个糟糕的优化器。

【讨论】:

  • 是我的错误,我删除了太多。有一个“where”条件可以得到相同的结果。
猜你喜欢
  • 2012-11-08
  • 2018-12-24
  • 2012-08-18
  • 1970-01-01
  • 2021-09-27
  • 2015-09-21
  • 2015-08-28
  • 2012-11-21
  • 1970-01-01
相关资源
最近更新 更多