重写查询替换不在

时间:2018-11-20 07:42:44

标签: sql oracle query-optimization

我想用一种删除table的方式重写下面的查询吗?

NOT IN

如果状态为select * from TRX_T TT, TRX_SUB TS where TT.CODE=TS.CODE and TT.SUBID= TS.ID and TS.VALUE=1 and TS.CODE=1 AND TS.ID=17 AND TT.STATUS NOT IN('T','R','C') ,我将使用IN

我要重写的原因是因为下面的oracle建议。

  

在执行的第5行使用的谓词“ TT”。“ STATUS” <>'C'   该计划在索引列“ STATUS”上包含一个表达式。这个   表达式使优化器无法有效地使用索引   表TT。

不同值的数量

union all

T 264 C 5489709 D 2987 J 924 L 529430 R 39382 S 5449 上的索引如下:TRX_T

5 个答案:

答案 0 :(得分:2)

如果要优化查询,则需要了解数据模型和数据。优化器说它不能有效地使用TRX_T上的索引。让我们看一下该复合索引:

  • CODE:用于加入条件
  • SUBID:用于加入条件
  • TYPE:未使用
  • STATUS:可以用作过滤器吗?
  • NO_SL:未使用

您的查询使用五个索引列中的三个。但是因为您在STATUS上有一个NOT IN表达式,所以优化程序不会使用索引来评估过滤器。因此,它将读取TRX_T中与TRX_SUB中的记录相匹配的每条记录,并评估表上的过滤器。

也许如果您将条件肯定地表示为TT.STATUS IN ('D','J','L', 'S'),则优化器可能可以使用SKIP SCAN来评估索引上的过滤器。

但是,如果将TRX_T.TYPE用作过滤器(或者重新排列索引列的顺序以使STATUSTYPE之前,索引使用会更有效,但是请勿这样做,因为这可能会破坏其他查询的稳定性)。

另一种选择是将表达式重写为NOT IN子查询(如果您在(TRX_T.CODE, TRX_T.SUBID)中具有 no null值,否则作为NOT EXISTS子查询):

select * from TRX_T TT, TRX_SUB TS
where TT.CODE=TS.CODE
and TT.SUBID= TS.ID
and TS.VALUE=1
and TS.CODE=1
AND TS.ID=17
AND (TT.CODE, TT.SUBID) NOT IN
     (select x.CODE, x.SUBID
      from trx_t x
      where x.status in ('T','R','C')
     )

但是,在该列表中具有STATUS值的TRX_T记录的数量非常大-它们是表的大部分-因此,评估该子查询可能比现在的价格昂贵。

请注意,通常需要注意的事项。在StackOverflow上调优查询是一个杯子的游戏。缺少太多信息(数据量,偏斜,其他索引,解释计划等),我们无法做任何猜测。

答案 1 :(得分:1)

使用显式联接而不是in可以用下面的方式替换

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<li class="menu main_menu_01"> 1.0 Main Menu </li>
  <ul class="panel">
								
    <li class="sub_menu_01"> 1.1 Sub Menu </li>
					
    <li class="menu main_menu_02"> 1.2 Sub Menu </li>
      <ul class="panel">
        <li class="sub_menu_02"> <a> 1.2.1 Sub Menu </a> </li>
        <li class="sub_menu_02"> <a> 1.2.2 Sub Menu </a> </li>	
      </ul>	
  </ul>
  
  
  
<li class="menu main_menu_01"> 2.0 Main Menu </li>
  <ul class="panel">
								
    <li class="sub_menu_01"> 2.1 Sub Menu </li>
					
    <li class="menu main_menu_02"> 2.2 Sub Menu </li>
      <ul class="panel">
        <li class="sub_menu_02"> <a> 2.2.1 Sub Menu </a> </li>
        <li class="sub_menu_02"> <a> 2.2.2 Sub Menu </a> </li>	
      </ul>	
 </ul>

答案 2 :(得分:1)

您可以尝试使用left join并过滤掉TT2.status is null,以便为您提供not in ('T','R','C')的那些记录

select * from TRX_T TT
   join  TRX_SUB TS on  TT.CODE=TS.CODE and TT.SUBID= TS.ID
   left join (select * from TRX_T where STATUS in ('T','R','C')) TT2 on 
   TT.CODE=TT2.CODE and TT.SUBID= TT2.SUBID
where TS.VALUE=1 and TS.CODE=1 AND TS.ID=17 and TT2.status is null

答案 3 :(得分:1)

您可以将minus 设置运算符用作

select *
  from TRX_T TT
  join TRX_SUB TS
    on ( TT.CODE = TS.CODE
     and TT.SUBID = TS.ID )
 where TS.VALUE = 1
   and TS.CODE = 1
   and TS.ID = 17
minus
select *
  from TRX_T TT
  join TRX_SUB TS
    on ( TT.CODE = TS.CODE
     and TT.SUBID = TS.ID )
 where TS.VALUE = 1
   and TS.CODE = 1
   and TS.ID = 17
   and TT.STATUS in ('T', 'R', 'C');

P.S。是的,从性能的角度来看,Not in大多是有问题的,因此,使用nvl时不应忘记不使用Not in函数。

答案 4 :(得分:0)

尝试以下操作,可以使用“除外”:

SELECT * 
FROM   trx_t TT, 
       trx_sub TS 
WHERE  TT.code = TS.code 
       AND TT.subid = TS.id 
       AND TS.value = 1 
       AND TS.code = 1 
       AND TS.id = 17 
EXCEPT 
SELECT * 
FROM   trx_t TT, 
       trx_sub TS 
WHERE  TT.status = 'T' 
        OR TT.status = 'R' 
        OR TT.status = 'C'