假设我有下表:
create table xxnvloror
( XX_ID NUMBER
, ITEM VARCHAR2(100)
, AMOUNT NUMBER
);
我在里面插入了10000张唱片 NULL
金额:
Declare
l_amount number;
BEGIN
for i in 1..10000 loop
if mod(i, 2) = 0 then
l_amount := null;
else
l_amount := i;
end if;
insert into xxnvloror
( XX_ID
, ITEM
, AMOUNT
)
VALUES
(
i
, 'item-'||i
, l_amount
);
end loop;
END;
我使用了以下两个查询:
select *
from xxnvloror
where amount is null or amount = 0;
select *
from xxnvloror
where nvl(amount, 0) = 0;
我查看了他们的计划,他们似乎并不重要:
Plan hash value: 1982466860
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5000 | 80000 | 15087 (1)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| XXNVLOROR | 5000 | 80000 | 15087 (1)| 00:00:01 |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("AMOUNT" IS NULL OR "AMOUNT"=0)
Plan hash value: 1982466860
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5001 | 80016 | 15088 (1)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| XXNVLOROR | 5001 | 80016 | 15088 (1)| 00:00:01 |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(NVL("AMOUNT",0)=0)
如果没有任何索引,使用 NVL
结束 OR
反之亦然?
2条答案
按热度按时间jm2pwxwz1#
在索引的范围内,在资源使用、i/o或性能方面没有区别。
如果没有任何索引,引擎将执行全表扫描。它将从堆中读取所有行,并计算 predicate 值以决定是否保留或丢弃每一行。两个 predicate 之间的cpu使用率差异很小。
另外, predicate 的选择性不够。它选择了大约50%的表。在这种情况下,全表扫描是最佳的。
goqiplq22#
实际上,这样的查询:
可以使用上的索引
amount
. 因此,该公式通常是优选的。我应该补充一点,oracle支持基于函数的索引。所以,如果你有一个索引
nvl(amount, 0)
,那么where nvl(amount, 0) = 0
最好是这样。