NVL vs DECODE

NVL and DECODE: Lazy vs Eager Evaluation

At first glance, Oracle’s NVL and DECODE seem like simple tools to handle NULL values, right? But under the hood, they have a different behavior some of them you may not know and this behavior is the topic of this blog post. If you’re using them interchangeably, you might be introducing performance issues or even runtime errors without knowing it.

This isn’t a new discovery; Tom Kyte demonstrated this behavior over 25 years ago in 2000. However, it’s still not widely known. For more insights, you can refer to the Ask TOM discussion titled “DECODE or NVL.

First I will explain the lazy and eager evaluation terms simply:

Eager evaluation refers to a programming or query evaluation strategy where all expressions (or arguments) are evaluated immediately, whether or not they are needed. In the context of SQL functions like NVL, eager evaluation means that both arguments of the function are evaluated, even if the first input is sufficient to determine the result.

In contrast, lazy evaluation only evaluates the second argument when it is actually needed. In the NVL example, lazy evaluation would mean that counter_function(col1) is only called when col1 is null. In SQL, CASE, DECODE and COALESCE expressions exhibit lazy evaluation behavior, only executing the second argument if the first condition isn’t met.

Let’s unravel the difference, starting with an eye-opener:

Here’s a common pattern that looks harmless:

You might expect that:

If col1 is not null, it should be returned directly without executing high_cost_computation(col1).
If col1 is null, only then should counter_function(col1) be called.

But that’s not what happens. Oracle evaluates both arguments of NVL, no matter what. That means counter_function(col1) is always executed even if col1 is not null. This can lead to unnecessary work, performance issues, or even runtime errors.

Here is the case :

I will create a table, a sequence for a counter, and an inline function (counter_function) – Prepare Phase:

Now i will query the sql statement for all the table records and see how much counter_function is executed.

NVL eager evaluate
NVL does not shirt circuit

It is not only for performance reasons, but you may also encounter unexpected errors.

Decode-Strict Evaluation
Decode and Coalesce short circuits

You may also use COALESCE which is part of the ANSI SQL standard.

While NVL is syntactically simpler, its lack of lazy evaluation can lead to both performance and some error issues in certain queries. If your fallback value involves a high cost function or potentially error-prone function, consider using DECODE or even CASE for safer, more efficient logic.

Hope it helps. See you on the next post : Part 2: Scalar Subquery Caching Behavior in a SQL Statement.


Discover More from Osman DİNÇ


Comments

Leave your comment