DECODE和CASE的效能比較

yangtingkun發表於2009-10-25

OracleDECODE函式功能很強,靈活運用的話可以避免多次掃描,從而提高查詢的效能。而CASE9i以後提供的語法,這個語法更加的靈活,提供了IF THEN ELSE的功能。

 

 

對於很多情況,DECODECASE都能解決問題,個人更傾向於使用DECODE,一方面是從8i保留下來的習慣,另一方面是DECODE的語法更加的簡潔,程式碼量要小一些。

不過今天在看Oracle9i的資料倉儲手冊時發現,Oracle在文件中提到CASE語句的效率會更高一些,尤其是CASE 表示式 WHEN 常量 THEN的語法,效率要比CASE WHEN 表示式 THEN的語法更高一些。對於後面這種說法倒是沒有太多的疑問,對於CASEDECODE效率高這種說法倒是第一次看到,印象中DECODE效率很高,應該不會比CASE的效率差。

到底效率如何,還是要具體的例項來說:

SQL> CREATE TABLE T AS
  2  SELECT A.*
  3  FROM DBA_OBJECTS A, DBA_MVIEWS;

Table created.

SQL> SELECT COUNT(*) FROM T;

  COUNT(*)
----------
   6075760

下面檢查DECODE和兩種CASE語句的效率:

SQL> SET ARRAY 1000
SQL> SET TIMING ON
SQL> SET AUTOT TRACE    
SQL> SELECT DECODE(OWNER, 'SYSTEM', 'SYSTEM', 'SYS', 'SYSTEM', 'USER')
  2  FROM T;

6075760 rows selected.

Elapsed: 00:00:07.24

Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  4245K|    68M| 13828   (1)| 00:03:14 |
|   1 |  TABLE ACCESS FULL| T    |  4245K|    68M| 13828   (1)| 00:03:14 |
--------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      47551  consistent gets
          0  physical reads
          0  redo size
   46288564  bytes sent via SQL*Net to client
      67317  bytes received via SQL*Net from client
       6077  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
    6075760  rows processed

SQL> SELECT CASE OWNER WHEN 'SYSTEM' THEN 'SYSTEM'
  2     WHEN 'SYS' THEN 'SYSTEM'
  3     ELSE 'USER' END
  4  FROM T;

6075760 rows selected.

Elapsed: 00:00:07.22

Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  4245K|    68M| 13828   (1)| 00:03:14 |
|   1 |  TABLE ACCESS FULL| T    |  4245K|    68M| 13828   (1)| 00:03:14 |
--------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      47551  consistent gets
          0  physical reads
          0  redo size
   46288578  bytes sent via SQL*Net to client
      67317  bytes received via SQL*Net from client
       6077  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
    6075760  rows processed

SQL> SELECT CASE WHEN WNER = 'SYSTEM' THEN 'SYSTEM'
  2     WHEN WNER = 'SYS' THEN 'SYSTEM'
  3     ELSE 'USER' END
  4  FROM T;

6075760 rows selected.

Elapsed: 00:00:07.23

Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  4245K|    68M| 13828   (1)| 00:03:14 |
|   1 |  TABLE ACCESS FULL| T    |  4245K|    68M| 13828   (1)| 00:03:14 |
--------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      47551  consistent gets
          0  physical reads
          0  redo size
   46288585  bytes sent via SQL*Net to client
      67317  bytes received via SQL*Net from client
       6077  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
    6075760  rows processed

測試結果確實是CASE的簡單表示式寫法效率最高,然後是CASE的另一種寫法,DECODE效率最低。但是對於600W的記錄,最終結果只有0.010.02秒的查詢,實在沒有辦法得出上面的結論,因為這個差別實在是太小,以至於任何其他的一些影響都足以改變測試結果,如要一定要得出結論,那麼結論就是3種方式的效率基本相同。

不過由於CASE表示式更加靈活,使得以前DECODE必須運用的一些技巧得以簡化,這時使用CASE方式,確實可以得到一些效能上的提高,比如:

SQL> SELECT DECODE(SIGN(OBJECT_ID), 1, '+', -1, '-', '0')
  2  FROM T;

6075760 rows selected.

Elapsed: 00:00:04.94

Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  4245K|    52M| 13840   (1)| 00:03:14 |
|   1 |  TABLE ACCESS FULL| T    |  4245K|    52M| 13840   (1)| 00:03:14 |
--------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      47551  consistent gets
          0  physical reads
          0  redo size
   31491431  bytes sent via SQL*Net to client
      67317  bytes received via SQL*Net from client
       6077  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
    6075760  rows processed

SQL> SELECT CASE WHEN OBJECT_ID > 0 THEN '+'
  2     WHEN OBJECT_ID < 0 THEN '-'
  3     ELSE '0' END
  4  FROM T;

6075760 rows selected.

Elapsed: 00:00:04.60

Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  4245K|    52M| 13840   (1)| 00:03:14 |
|   1 |  TABLE ACCESS FULL| T    |  4245K|    52M| 13840   (1)| 00:03:14 |
--------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      47551  consistent gets
          0  physical reads
          0  redo size
   31491449  bytes sent via SQL*Net to client
      67317  bytes received via SQL*Net from client
       6077  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
    6075760  rows processed

這裡CASE帶來效能提升的主要原因實際上是CASE避免了SIGN函式的呼叫,而並不是CASE本身的效能要高於DECODE,事實上如果這裡使用SIGN並利用CASE的所謂高效語法:

SQL> SELECT CASE SIGN(OBJECT_ID) WHEN 1 THEN '+'
  2     WHEN -1 THEN '-'
  3     ELSE '0' END
  4  FROM T;

6075760 rows selected.

Elapsed: 00:00:04.97

Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  4245K|    52M| 13840   (1)| 00:03:14 |
|   1 |  TABLE ACCESS FULL| T    |  4245K|    52M| 13840   (1)| 00:03:14 |
--------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      47551  consistent gets
          0  physical reads
          0  redo size
   31491445  bytes sent via SQL*Net to client
      67317  bytes received via SQL*Net from client
       6077  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
    6075760  rows processed

可以看到,這時效率比DECODE還低。

根據上面的測試可以得出結論,無論是DECODE還是CASE方式的兩種寫法,執行效率沒有明顯的差別。

 

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4227/viewspace-617385/,如需轉載,請註明出處,否則將追究法律責任。

相關文章