【发布时间】:2018-07-12 12:28:52
【问题描述】:
我有一个类似下面的查询,我想使用连接重写它。此查询需要 4-5 小时才能在生产环境中执行并返回 GB 的数据。
为了重组它,我使用本地数据库中的一个小数据集检查了它的执行计划,显示成本为 782。
对此,我的同行建议我们不应该在这个查询中使用 IN 和 NOT IN 来提高它的性能。
注意::"SELECT a3.pk_id FROM tableB a3 WHERE ROWNUM <= 150"下面的子查询只是在本地尝试,这样我就可以在IN子句中获取一些数据。实际的子查询没有 ROWNUM 和 where 条件中的一些子句。
原始查询 1)
SELECT DISTINCT
a1.fk_id
FROM
tableA a1
WHERE a1.master_id IN (
SELECT DISTINCT
a2.master_ref
FROM
tableB a2
WHERE a2.pk_id IN ( SELECT a3.pk_id FROM tableB a3 WHERE ROWNUM <= 150)
)
AND a1.fk_id NOT IN ( SELECT a3.pk_id FROM tableB a3 WHERE ROWNUM <= 150)
我再次重写它,如下所示,这给了我相同的输出,执行计划中的成本与 114 相同。
查询 2)
SELECT DISTINCT
a1.fk_id
FROM
tableA a1, tableB a2
WHERE a1.master_id = a2.master_ref
AND a2.pk_id IN (
(SELECT a3.pk_id FROM tableB a3 WHERE ROWNUM <= 150)
)
AND a1.fk_id NOT IN (
(SELECT a3.pk_id FROM tableB a3 WHERE ROWNUM <= 150)
) -- This query gives correct result as above.
但是因为我想完全避免 IN 和 NOT IN 子句,并希望尽可能使用 JOIN。我使用 JOIN/LEFT JOIN/EXISTS/NOT EXISTS 尝试了更多查询,但每次我的输出都与所需的不同。
我尝试过的一个查询如下:
查询 3)
SELECT DISTINCT
a1.fk_id
FROM
tableA a1, ( SELECT a3.pk_id FROM tableB a3 WHERE ROWNUM <= 150 ) pkgObjs, tableB a2
WHERE a1.ida3b5 = a2.master_ref
AND a2.master_id = pkgObjs.pk_id
AND a1.fk_id <> pkgObjs.pk_id;
-- This query is not giving me intended results.
我有几个与此相关的问题::
1) 为什么我的第三个查询(使用连接)没有给我适当的结果? -- 逻辑上似乎是一样的
2) IN 和 NOT IN 在这种情况下是否还有其他选择,我们应该完全避免吗?
3) 就性能而言,第二次查询仍然很昂贵吗?
我是 SQL 新手,我正在尝试分析所有可能的场景。如果我能在使用联接编写此查询时获得一些帮助,那就太好了。
【问题讨论】:
-
First 使用
ROWNUM <= 150对子查询进行测试没有预期结果,因为您使用了表中的随机 150 行。 第二没有这样的事情没有IN和NOT IN的查询总是比有它们更好。您必须调查生产执行计划中的问题并做出反应。 -
感谢您的回复。为了消除由于 ROWNUM 导致的随机值的概率,我创建了一个包含 50000 条记录的 temp_table。现在,当我使用 temp_table 而不是 ROWNUM 子查询时,我可以看到相当大的性能改进。早些时候,有 50000 条记录的查询需要 140 秒才能执行,而 temp_table 只需 12 秒。为什么会这样?
标签: sql oracle query-performance