sql查询中,case和decode的比较

 

Oracle的DECODE函数功能很强,灵活运用的话可以避免多次扫描,从而提高查询的性能。而CASE是9i以后提供的语法,这个语法更加的灵活,提供了IF THEN ELSE的功能。

 对于很多情况,DECODE和CASE都能解决问题,个人更倾向于使用DECODE,一方面是从8i保留下来的习惯,另一方面是DECODE的语法更加的简洁,代码量要小一些。

不过今天在看Oracle9i的数据仓库手册时发现,Oracle在文档中提到CASE语句的效率会更高一些,尤其是CASE 表达式 WHEN 常量 THEN的语法,效率要比CASE WHEN 表达式 THEN的语法更高一些。对于后面这种说法倒是没有太多的疑问,对于CASE比DECODE效率高这种说法倒是第一次看到,印象中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.01到0.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方式的两种写法,执行效率没有明显的差别。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DECODECASE WHEN都是在Oracle数据库用于条件判断和值替换的语句。它们可以根据给定的条件返回不同的结果。 DECODE函数是Oracle特有的函数,它接受一个或多个表达式和一系列条件-结果对。它会逐个比较表达式和条件,如果找到匹配的条件,则返回对应的结果。如果没有找到匹配的条件,则返回默认结果。DECODE函数的语法如下: ```sql DECODE(expression, search1, result1, search2, result2, ..., default_result) ``` CASE WHEN语句是标准SQL语句,在Oracle和其他数据库都可以使用。它使用类似于编程语言的if-else语句的结构。CASE WHEN语句的语法如下: ```sql CASE WHEN condition1 THEN result1 WHEN condition2 THEN result2 ... ELSE default_result END ``` DECODECASE WHEN在功能上是相似的,都可以根据条件返回不同的结果。但它们在语法和使用上有一些区别DECODE函数的语法比较简洁,适用于只有一个表达式和多个条件-结果对的情况。它的执行效率相对较高,尤其是在使用常量作为条件时。 CASE WHEN语句的语法更加灵活,可以处理复杂的条件逻辑。它适用于多个条件和多个结果的情况。CASE WHEN语句的可读性更好,更容易理解和维护。 总的来说,如果条件比较简单且只有一个表达式,可以使用DECODE函数。如果条件比较复杂或需要处理多个条件和多个结果,可以使用CASE WHEN语句。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值