Oracle 11g,如何加快“in”查询

Posted

技术标签:

【中文标题】Oracle 11g,如何加快“in”查询【英文标题】:Oracle 11g, how to speed up an 'in' query 【发布时间】:2016-05-18 07:37:27 【问题描述】:

我试图创建一个视图并且需要创建一个列来显示“somenumber”列是否存在于其他表中。下面的代码工作但非常缓慢。是否可以将表声明为(从veryYugeTable 中选择一些数字)并检查该表,而不是为每条记录发送此查询或使用其他方式来加快查看速度?

case 
         when someOtherTable.someNumber in(select someNumber from veryYugeTable) then 'exists' 
         else 'doesn't exist' 
end as "someColumn" 

【问题讨论】:

在 someNumber = someOtherTable.someNumber 上使用 left joinveryYugeTable 然后将 casewhen 子句更改为veryYugeTable.Column is null then '不存在' else 'exits' 请发布视图查询及其解释计划。没有看到问题不容易提供解决方案。请参阅here 一些提示。 【参考方案1】:

查询看起来不错。您应该在veryYugeTable.someNumber 上有一个索引。

有时优化器处理相关子查询比处理非相关子查询更好,因此您可以尝试:

case
  when exists 
  (
    select * 
    from veryYugeTable
    where veryYugeTable.someNumber = someOtherTable.someNumber
  ) then 'exists' 
  else 'doesn''t exist' 
end as "someColumn"

(好吧,因为这个查询和你的完全一样,优化器应该得到相同的执行计划,但情况并非总是如此。)

但如前所述:确保首先拥有该索引。

【讨论】:

谢谢,索引似乎是个好主意。【参考方案2】:

如果您执行以下操作,您可能会发现标量子查询缓存会带来一些好处:

coalesce((select 'exists'
          from   veryyugetable vyt
          where  vyt.somenumber = someOtherTable.someNumber
          and    rownum = 1),
         'doesn''t exist') somecolumn

注意如果vyt.somenumber 是唯一列,则不需要and rownum = 1。另外,我建议索引vyt.somenumber 列。

【讨论】:

【参考方案3】:

使用左连接而不是将 in 子句放在 select 中:

left join veryYugeTable on someNumber = someOtherTable.someNumber

调整你的 case when 语句如下:

case 
         when veryYugeTable.OtherColumn is null then 'doesn''t exist' 
         else 'exist' 
end as "someColumn"

【讨论】:

如果someNumber 不是veryYugeTable 表中的PK(唯一),这将失败(= 产生重复) 遗憾的是 someNumber 在veryYugeTable 不是PK。

以上是关于Oracle 11g,如何加快“in”查询的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Oracle 11g 的“选择”查询中添加偏移量?

如何在 oracle db 11g - centos 6 中启用查询日志

如何加快这个oracle选择查询?

在 Oracle 11g 中转换动态查询以使用绑定变量

Linux7安装oracle11g报错 Error in invoking target ‘agen

oracle 11g 别名查询