Infrastructure at your Service

The DUAL table is automatically created by Oracle and contains one column (DUMMY) and one row (x value).

This table is often used by SQL developer in PL/SQL code (Package, Functions, Trigger) to initialize variables storing technical information such as for example SYSDATE, USER or HOSTNAME.

Querying DUAL table is generally faster  as we can see below:

SQL> select sysdate from dual;

SYSDATE
---------
05-OCT-21

Elapsed: 00:00:00.01

Execution Plan
----------------------------------------------------------
Plan hash value: 1388734953

-----------------------------------------------------------------
| Id  | Operation        | Name | Rows  | Cost (%CPU)| Time     |
-----------------------------------------------------------------
|   0 | SELECT STATEMENT |      |     1 |     2   (0)| 00:00:01 |
|   1 |  FAST DUAL       |      |     1 |     2   (0)| 00:00:01 |
-----------------------------------------------------------------


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          0  consistent gets
          0  physical reads
          0  redo size
        554  bytes sent via SQL*Net to client
        386  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

 

But what happens when this “SELECT FROM DUAL” is executed several times into the application :

Let’s execute it for 100, 1000, 10000, 100000 and 1000000 executions

SQL> declare
        v_date date;
begin
 for rec in 1..100 loop
        select sysdate into v_date from dual;
  end loop;
end;  2    3    4    5    6    7
  8  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.01
SQL> declare
        v_date date;
begin
 for rec in 1..1000 loop
        select sysdate into v_date from dual;
  end loop;
end;  2    3    4    5    6    7
  8  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.01
SQL> declare
        v_date date;
begin
 for rec in 1..10000 loop
        select sysdate into v_date from dual;
  end loop;
end;
  2    3    4    5    6    7    8
  9  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.08
SQL> declare
        v_date date;
begin
 for rec in 1..100000 loop
        select sysdate into v_date from dual;
  end loop;
end;  2    3    4    5    6    7
  8  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.85
SQL> declare
        v_date date;
begin
 for rec in 1..1000000 loop
        select sysdate into v_date from dual;
  end loop;
end;
  2    3    4    5    6    7    8
  9  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:08.34
SQL>

 

Let’s execute now a PL/SQL block to assign directly the variable v_date with SYSDATE instead of using “SELECT FROM DUAL”:

SQL> declare
        v_date date;
begin
 for rec in 1..100 loop
        v_date := sysdate;
  end loop;
end;
  2    3    4    5    6    7    8
  9  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.00
SQL> declare
        v_date date;
begin
 for rec in 1..1000 loop
        v_date := sysdate;
  end loop;
end;
  2    3    4    5    6    7    8
  9  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.00
SQL> declare
        v_date date;
begin
 for rec in 1..10000 loop
        v_date := sysdate;
  end loop;
end;
  2    3    4    5    6    7    8
  9  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.01
SQL> declare
        v_date date;
begin
 for rec in 1..100000 loop
        v_date := sysdate;
  end loop;
end;
  2    3    4    5    6    7    8
  9  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.14
SQL> declare
        v_date date;
begin
 for rec in 1..1000000 loop
        v_date := sysdate;
  end loop;
end;
  2    3    4    5    6    7    8
  9  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:01.28
SQL>

 

Conclusion:

Nb of executions SELECT FROM DUAL Assigning variable
100
1 ms
0 ms
1000 1 ms
0 ms
10000 8 ms
1 ms
100000 85 ms
14 ms
1000000 8.34 sec
1.28 sec

 

“SELECT FROM DUAL” is always slower than “Assigning variable”:

  • 8 times more slower for 10000 executions
  • 6 times more slower for 100000 executions
  • More than 8 times more slower for 1000000 executions

From a performance point of vew, “SELECT FROM DUAL” must be avoided to initialize variable because when you query the DUAL table in a PL/SQL block, oracle optimizer does a roundtrip between the PL/SQL engine and the SQL engine. For few rows, it’s fast, but for several rows (Ex.: 1000000) the “SELECT FROM DUAL” is inefficient because oracle will do 1000000 roundtrips between the PL/SQL engine and the SQL engine.

I have seen plenty of applications where the “SELECT FROM DUAL” is used everywhere (Ex. : “SELECT FROM DUAL” in a Logon trigger !!!) while we can use a simple “Assigning variable” and changing the code has increased the performance of the application significantly.

 

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Lazhar Felahi
Lazhar Felahi

Consultant