我使用的是Oracle 12.2版本。我有一个SQL,它有两个过滤条件来从一个巨大的表中获取NULL值。我已经将IS NULL
转换为NVL (OFF_CODE, -1)=-1
和nvl(off_date,'01-JAN-1900')= '01-JAN-1900'
。
我已经在两列上创建了基于函数的复合索引,然后我采取了解释计划,我粘贴在这里。成本从800万降到现在的122万。
看到这个计划后,我非常高兴。但SQL会持续运行几分钟在更改之前,它在15分钟内响应。成本降低后React不快是什么问题?如何替换IS NULL以获得更好的性能?
-------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 192 | 122 (1)| 00:00:01 |
| 1 | HASH GROUP BY | | 4 | 192 | 122 (1)| 00:00:01 |
| 2 | NESTED LOOPS | | 146 | 7008 | 121 (0)| 00:00:01 |
| 3 | NESTED LOOPS | | 148 | 7008 | 121 (0)| 00:00:01 |
| 4 | TABLE ACCESS BY INDEX ROWID BATCHED| TABLE_NAME1 | 4 | 128 | 8 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | INDEX_TABLE_NAME1 | 4 | | 4 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | INDEX_TABLE_NAME2 | 37 | | 3 (0)| 00:00:01 |
| 7 | TABLE ACCESS BY INDEX ROWID | TABLE_NAME2 | 37 | 592 | 36 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
5 - access(NVL("OFF_CODE_ID",(-1))=(-1) AND NVL("OFF_DATE",'01-JAN-1900')='01-JAN-1900')
6 - access("I"."ITEM_ID"="IGP"."ITEM_ID")
我的查询
SELECT /*+ index (i, INDEX_TABLE_NAME1) */
i.item_id,
SUM(coalesce(igp. DEPR_cost, 0) + coalesce(igp.act_dprctn_cost, 0)) depr_cost
FROM
TABLE_NAME1 i,
TABLE_NAME2 igp
WHERE 1 = 1
AND i.Item_id = igp.item_id
AND nvl(i.off_code_id,-1) = -1
AND nvl(i.off_date,'01-JAN-1900') = '01-JAN-1900'
GROUP BY i.item_id;<br/>
我的指数:
create index INDEX_TABLE_NAME1 on TABLE_NAME1( nvl( off_code_id,-1),nvl( off_date,'01-JAN-1900'));
2条答案
按热度按时间9avjhtql1#
如果表列上的空值百分比低于5%,则可以提升索引的使用。如果是这种情况,你可以使用第二个表作为驱动表,并将查询写成:
此查询将受益于以下索引:
顺便说一句,我不明白查询使用表#1做什么,因为所有的值都来自表#2。只是好奇。。
tvmytwxo2#
我的印象是,你只对这两个字段为NULL的记录感兴趣。您是否有其他查询可以在这些列上筛选以查找实际值?如果没有,为什么不创建一个过滤索引?
然后将SQL改回
注意事项:
-1
和1 jan 1900
的记录JOIN .. ON
结构而不是你现在所拥有的,我怀疑它会在执行计划中产生任何差异,但它只是可读性更好,因此更不容易出错。