Преимущество использования NVL перед OR в запросе - PullRequest
1 голос
/ 27 мая 2020

Допустим, у меня есть таблица ниже:

create table xxnvloror
(   XX_ID       NUMBER
,   ITEM        VARCHAR2(100)
,   AMOUNT      NUMBER
);

И я вставил в нее 10000 записей, поместив некоторые NULL значения в Amounts:

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;

Я использовал 2 запросы ниже:

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 ]

2 голосов
/ 27 мая 2020

На самом деле такой запрос:

where amount is null or amount = 0

может использовать индекс на amount. Следовательно, эта формулировка обычно предпочтительнее.

Я должен добавить, что Oracle поддерживает индексы на основе функций. Итак, если у вас есть индекс на nvl(amount, 0), тогда where nvl(amount, 0) = 0 будет предпочтительнее.

1 голос
/ 27 мая 2020

При выборе индексов не будет разницы в использовании ресурсов, вводе-выводе или производительности.

Без индексов механизм выполнит полное сканирование таблицы. Он будет читать все строки из кучи и вычислять значение предиката, чтобы решить, будет ли он сохранять или отбрасывать каждую строку. Разница в использовании ЦП между обоими предикатами незначительна.

Кроме того, ваш предикат недостаточно избирательный. Он выбирает около 50% таблицы. В этом случае оптимальным является сканирование всей таблицы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...