加速不存在的查询

时间:2014-05-12 22:19:57

标签: sql oracle optimization not-exists

我有一个像这样工作的oracle查询:

SELECT * 
FROM VW_REQUIRED r
JOIN VW_ACTUAL a ON a.person_id = r.person_id AND a.target_id = r.target_id

必需的是详细说明所有必需培训材料的视图,实际是详细说明最近拍摄的特定课程的视图。这些查询中的每一个本身都需要不到2秒的时间来生成10k到10万行。

我想做的是:

SELECT *
FROM VW_REQUIRED r
WHERE NOT EXISTS ( SELECT 1 FROM VW_ACTUAL a WHERE a.person_id = r.person_id AND a.target_id = r.target_id) 

并且需要超过20秒(我没有让它完成,因为这显然太长了。

然后我决定做一些与众不同的事情,我将原来的JOIN作为左连接,这样它就会向我显示所有必需的训练,以及实际的训练,只有它存在。

这很有效,而且速度非常快。

但是我想要一份没有实际培训的课程清单(即我们需要开展培训并接受培训的人员......)

当我尝试类似

SELECT * 
FROM VW_REQUIRED r
LEFT JOIN VW_ACTUAL a ON a.person_id = r.person_id AND a.target_id = r.target_id
WHERE r.person_id = null

我没有回来。我不确定我是否可以过滤掉没有实际结果的行。通常情况下,我会使用WHERE NOT EXISTS,但其上的效果非常慢(而且我不认为我可以在视图上放置索引......)

我设法做出了一些有效的改变,但看起来很糟糕,我确信这是一个更好的解决方案。

SELECT
  who, where_from, mand, target_id, grace_period, date_taken
FROM (
    SELECT
      r.person_id who,
      r.where_from where_from,
      r.mand mand,
      r.target_id target_id
      r.grace_period grace_period,
      nvl(a.date_taken, to_date('1980/01/01','yyyy/mm/dd')) date_taken
    FROM VW_REQUIRED r
    LEFT JOIN VW_ACTUAL a ON a.person_id = r.person_id AND a.target_id = r.target_id
)
WHERE date_taken = to_date('1980/01/01','yyyy/mm/dd')

2 个答案:

答案 0 :(得分:3)

我认为你只混合了表名。你能改变最后的地方

吗?

a.person_id is null

所以你的查询应该是这样的:

SELECT * 
FROM VW_REQUIRED r
LEFT JOIN VW_ACTUAL a ON a.person_id = r.person_id AND a.target_id = r.target_id
WHERE a.person_id is null

或者也许是“老”的方式?

SELECT * 
FROM
VW_REQUIRED r,
VW_ACTUAL a
WHERE  r.person_id = a.person_id(+) 
AND r.target_id = a.target_id(+)
AND a.person_id is null  

答案 1 :(得分:0)

也许你的问题来自不存在的查询中的错误计划。

您能告诉我们此查询的计划吗?

SELECT *
FROM VW_REQUIRED r
WHERE NOT EXISTS ( SELECT 1 FROM VW_ACTUAL a WHERE a.person_id = r.person_id AND a.target_id = r.target_id) 

尝试更改连接算法(/ + use_nl(a) /或/ + use_hash(a) /)。 我认为这是一个嵌套循环。也许你必须在这个例子中加入一个哈希联接,就像这样

SELECT *
FROM VW_REQUIRED r
WHERE NOT EXISTS ( SELECT /*+use_hash(a)*/ 1 FROM VW_ACTUAL a WHERE a.person_id = r.person_id AND a.target_id = r.target_id)