【问题标题】:ORACLE LIKE with multiple values具有多个值的 ORACLE LIKE
【发布时间】:2019-03-18 17:31:48
【问题描述】:

我在 ORACLE 中有以下查询,由于两个喜欢之间的 OR 需要很长时间才能运行。

select pat_mrn_id,surgery_date, proc_name  
from or_log_all_proc, or_proc, or_log, patient
where 
upper(proc_name) like ('%CRANIOTOMY ANEURYSM%') OR upper(proc_name) like 
('CLIPPING%ANEURYSM')

任何有助于有效编写查询的帮助将不胜感激。 谢谢! JH

【问题讨论】:

  • OR 不是 WHERE 子句中昂贵的部分。这是'LIKE '%anything%'。为了解决第一个条件,需要扫描数据库中的每一行。仅在第一个条件下尝试它,我怀疑性能会不会有很大提高。 (即使您解决了交叉连接 4 个表的问题,根据以下答案)

标签: sql oracle performance query-optimization sql-like


【解决方案1】:

来自 or_log_all_proc、or_proc、or_log、患者

您的 SELECT 不包含 无连接条件,因此它将从其中三个表中生成所有记录的 产品,并生成由LIKE 子句。这是您的性能问题的根源。

解决方案非常简单。使用适当的键列正确连接表。

顺便说一句,这是使用 ANSI 92 连接语法的好处。通过明确连接的类型,如果我们真的想生成一个产品,我们必须实际编写 CROSS JOIN,并防止我们意外地这样做。

期望 LIKE '%anything%' 快也是徒劳的

在一定程度上。很可能它是全表扫描,但它是一个索引列,然后我们可能会得到一个全快速扫描。即使它只是一个不一定是灾难性的 FTS,尤其是在桌子很小或狭窄的情况下。与大多数调优任务一样,它实际上取决于细节。

【讨论】:

  • 期待LIKE '%anything%' 快也是徒劳的,不管OR(但您关于交叉连接的观点更为中肯)
  • @MatBailie - 是的,也许吧。如果它是一个小表或索引列,那么它可能没问题。
【解决方案2】:

使用正则表达式代替LIKE。但更重要的是,您缺少JOIN 条件:

select pat_mrn_id,surgery_date, proc_name  
from or_log_all_proc join
     or_proc
     on ???? join
     or_log
     on ????
     patient
     on ????
where regexp_like(upper(proc_name), '(CRANIOTOMY ANEURYSM)|(CLIPPING.*ANEURYSM)');

性能问题更有可能是由于缺少JOIN 条件而不是LIKE

【讨论】:

    【解决方案3】:

    LIKE 无论如何都会很慢,不是吗?不过,如果您确定是 OR 导致问题,请尝试 UNION,例如

    select pat_mrn_id,surgery_date, proc_name  
    from or_log_all_proc, or_proc, or_log, patient
    where upper(proc_name) like ('%CRANIOTOMY ANEURYSM%')
    union all
    select pat_mrn_id,surgery_date, proc_name  
    from or_log_all_proc, or_proc, or_log, patient
    where upper(proc_name) like ('CLIPPING%ANEURYSM')
    

    另外,我猜这不是您真正使用的查询 - FROM 子句中有 4 个表,没有任何连接 - 笛卡尔积不是最佳选择。

    【讨论】:

      【解决方案4】:

      尝试使用union all 而不是or 以获得更好的性能

       select pat_mrn_id,surgery_date, proc_name  
       from or_log_all_proc, or_proc, or_log, patient
       where 
       upper(proc_name) like ('CLIPPING%ANEURYSM')
       union all     
       select pat_mrn_id,surgery_date, proc_name  
       from or_log_all_proc, or_proc, or_log, patient
       where upper(proc_name) like ('%CRANIOTOMY ANEURYSM%')
      

      另外我认为您忘记使用唯一 ID 连接表

      【讨论】:

      • 谢谢大家。 Union 和 regexp_like 都很好用。
      猜你喜欢
      • 2023-01-18
      • 2011-08-02
      • 2013-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-02
      • 1970-01-01
      相关资源
      最近更新 更多