没有 Not In 和 In 使用连接的 SQL 查询优化
Posted
技术标签:
【中文标题】没有 Not In 和 In 使用连接的 SQL 查询优化【英文标题】:SQL Query optimization without Not In and In using joins 【发布时间】: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 秒。为什么会这样?
【参考方案1】:
如果我理解得很好,这是您可以使用的最简单的查询:
SELECT
A.FK_ID
FROM
TABLEA A, TABLEB B
WHERE
A.PK_ID = B.PK_ID
AND A.FK_ID <> B.PK_ID
--AND ROWNUM <= 150
请注意,ROWNUM
已被注释,因为如果没有订购,您就无法相信它的结果。
如果执行计划成本高,则需要分析索引,有时像下一个这样的小改动,就会产生很大的不同:
SELECT
B.FK_ID
FROM
TABLEA B, TABLEB A
WHERE
B.PK_ID = A.PK_ID
AND B.PK_ID <> A.FK_ID
【讨论】:
以上是关于没有 Not In 和 In 使用连接的 SQL 查询优化的主要内容,如果未能解决你的问题,请参考以下文章
sql中的in与not in,exists与not exists的区别
sql中的in与not in,exists与not exists的区别
sql中的in与not in,exists与not exists的区别
有没有办法在 SQL 中将 EXCEPT 语句重写为 NOT IN 语句?