sql—在查询上或查询中使用nvl的优点

qfe3c7zg  于 2021-08-13  发布在  Java
关注(0)|答案(2)|浏览(322)

假设我有下表:

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 反之亦然?

jm2pwxwz

jm2pwxwz1#

在索引的范围内,在资源使用、i/o或性能方面没有区别。
如果没有任何索引,引擎将执行全表扫描。它将从堆中读取所有行,并计算 predicate 值以决定是否保留或丢弃每一行。两个 predicate 之间的cpu使用率差异很小。
另外, predicate 的选择性不够。它选择了大约50%的表。在这种情况下,全表扫描是最佳的。

goqiplq2

goqiplq22#

实际上,这样的查询:

where amount is null or amount = 0

可以使用上的索引 amount . 因此,该公式通常是优选的。
我应该补充一点,oracle支持基于函数的索引。所以,如果你有一个索引 nvl(amount, 0) ,那么 where nvl(amount, 0) = 0 最好是这样。

相关问题