sql - 重写查询替换不在
问题描述
我想以删除的方式重新编写以下查询,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
我会使用union all
我想重写的原因是因为下面的 oracle 推荐。
在执行计划的第 5 行使用的谓词 "TT"."STATUS"<>'C' 包含索引列 "STATUS" 上的表达式。此表达式阻止优化器有效地使用表 TT 上的索引。
不同值的数量
T 264
C 5489709
D 2987
J 924
L 529430
R 39382
S 5449
上的索引TRX_T
是这样的:(CODE,SUBID,TYPE,STATUS,NO_SL)
解决方案
如果您想调整查询,您需要了解您的数据模型和数据。优化器说它不能有效地使用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)
否则作为 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 上调优查询是个小游戏。缺少太多信息(数据量、偏差、其他索引、解释计划等),我们只能做猜测之外的任何事情。
推荐阅读
- microsoft-graph-api - 通过 Graph API 将文件从 OneDrive 帐户安全地提供给 webapp 用户
- c# - 在 NUnit 测试期间创建 Microsoft PointOfService 的 PosExplorer 对象时出现异常
- makefile - 编译驱动程序时条件 CCOPT 未传递给 subMakefile
- c++ - 当其中一个函数无法编译时,函数重载查找如何工作?
- swift - MyUItableview 滚动时聚集
- matlab - 未能创建 3 维到 2D 点动画
- python - 绘制排序值
- mysql - Delphi 和 MySQL - 定期弹出数据库错误 - 如何修复它?
- ansible - Ansible - 'delegate_to' 超时连接到远程主机
- if-statement - POWER BI - if 条件下的最大值