我想用一种删除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
答案 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
用作过滤器(或者重新排列索引列的顺序以使STATUS
在TYPE
之前,索引使用会更有效,但是请勿这样做,因为这可能会破坏其他查询的稳定性)。
另一种选择是将表达式重写为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'