使用 NOT IN(Oracle Sql Developer)的查询性能优化

Posted

技术标签:

【中文标题】使用 NOT IN(Oracle Sql Developer)的查询性能优化【英文标题】:Query Performance Opttimization using NOT IN(Oracle Sql Developer) 【发布时间】:2014-07-04 14:23:11 【问题描述】:

我一直在尝试优化以下查询的性能。我请求这个领域的所有专家给我一个帮助和建议。

我有应用程序。 70k 条记录,我的要求是删除重复项。我需要提高以下查询的性能。

select *
  from x.vw_records
 where id not in
       (select distinct id
          from x.vw_datarecords
         where effective_date >= trunc(sysdate - 30)
           and book in (select book_shortname from x.vw_datarecords))
union
select distinct id
  from x.vw_historyrecords
 where effective_date >= trunc(sysdate - 30)
   and book in (select book_shortname from x.vw_datarecords)
union
select distinct id
  from x.vw_transactiondata
 where effective_date >= trunc(sysdate - 30)
   and book in (select book_shortname from x.vw_datarecords);
union
  select distinct id
    from x.vw_cashdata
   where effective_date >= trunc(sysdate - 30)
     and book in (select book_shortname from x.vw_datarecords)

目前数一数需要十分钟。使用计数(*)的行数。建议我调整此查询的性能。

提前致谢。

【问题讨论】:

你能读懂这个查询吗?我不能。 我认为您在第一个联合之前缺少左括号,并且查询末尾的左括号不应该存在,仅供参考。看起来无效 我会看看你是否真的需要在所有地方都使用 DISTINCT,因为这可能会对性能产生很大影响。如果 1 块的结果自然不会与第二块重叠,也请使用 UNION ALL 而不是 UNION,因为您正在让它做额外的工作来确定是否有任何重叠。 @BrianDeMilia 抱歉出现错误,查询正在执行。我需要的只是提高查询的性能。如果您有任何想法,请建议我。 我只是出于格式化目的对其进行了编辑。为每个表或至少一个列和索引列表提供 DDL 会有所帮助。如果您可以通过以一种或另一种方式使用其他列来避免使用 DISTINCT 并使用 UNION ALL 而不是 UNION 来避免可能会提高性能的重复项。 DISTINCT 通常不利于性能。 【参考方案1】:

我总是发现用左连接 + where iS NULL 替换 NOT IN(查询)会获得更好的性能

示例而不是:

select *
from x.vw_records
where id not in (
    select distinct id
    from x.vw_datarecords
    where effective_date >= trunc(sysdate - 30)
        and book in (
            select book_shortname from x.vw_datarecords
        )

使用:

select *
from x.vw_records vr
left join vw_datarecords vdr on vr.id = vdr.id
    and effective_date >= trunc(sysdate - 30)
        and book in (
            select book_shortname from x.vw_datarecords
        )
where vdr.id IS NULL

此外,您有时可以通过分组而不是区分来获得明显更好的性能。

【讨论】:

找到了我的答案,使用 Equi join 非常划算。【参考方案2】:

我怀疑您需要索引。 您在查询中涉及的表上有哪些索引?

& 是时候学习如何使用“解释计划”了,它是查询优化的重要工具。得到一个并不难。然而,它们可能有点难以理解。请在您的问题中包含解释计划输出。

    EXPLAIN PLAN FOR
      <<Your SQL_Statement here>>
    ;

    SET LINESIZE 130
    SET PAGESIZE 0
    SELECT * FROM table(DBMS_XPLAN.DISPLAY);

当你使用“union”时,使用“select distinct”绝对是零好处,不要同时做两个,只做一个。

【讨论】:

[使用解释计划][1] [DBMS_XPLAN][2] [Oracle 优化器 - 解释解释计划][3] [1]:docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_xplan.htm [2]:docs.oracle.com/cd/B10500_01/server.920/a96533/ex_plan.htm [3 ]:blogs.oracle.com/optimizer/entry/explain_the_explain_plan_white 假设 id=name,一个公司可能有两个同名不同领域的员工。所以在这种情况下,你需要使用 distinct 和 union。如果我错了,请澄清我。【参考方案3】:

如果您可以尝试使用存在/不存在子句代替 in/not in (http://www.techonthenet.com/sql/exists.php)。这通常运行得更快。

【讨论】:

对 in 使用 Exists 关键字给我一个错误。在性能方面两者几乎相同。对于 50 行,两者的提取时间(NOT EXISTS 代替 NOT IN)几乎是 8 秒。

以上是关于使用 NOT IN(Oracle Sql Developer)的查询性能优化的主要内容,如果未能解决你的问题,请参考以下文章

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

使用“使用严格”作为“使用强”的备份

Kettle java脚本组件的使用说明(简单使用升级使用)

MVVM基本使用