SQL可以写的很笨重,也可以写的很优雅,本文从一个简单的查询v$SQL/DBA_HIST_SQLSTAT的语句开始,介绍几种常用的优雅SQL编写方式

在分析v$sql 或者 dba_hist_sqlstat的时候,由于时常需要计算单次执行的相关指标,目前看到多数人用的是类似这样的写法


elapsed_time / CASE 
        WHEN executions = 0
        THEN 1
        ELSE executions
      END


或者


elapsed_time /  decode(executions,0,1,executions)


目的是避免executions(或者executions_delta)为0时导致除数为0的错误。 不能说这样写有错,但是不够优雅。优雅的做法是什么呢?应该是使用greatest函数,写法是:


elapsed_time /greatest(executions ,1)


greatest函数返回参数列表中最大的一个,所以,达到了如果executions为0,就返回1的效果,是不是清爽优雅了许多?

还有一个用法,就是需要把时间由原始微秒转换成秒或者毫秒的时候,目前多数的写法是

转成秒:


elapsed_time / 100000


或者

转成毫秒:


elapsed_time / 1000


转成毫秒还好,后面3个0,转成秒时,后面6个0,有没有特别担心写少一位或者多写一位?

其实我上面的举例就少了一位,是错误的 ,但是有多少人能够及时看出来?

这时候可以优雅地利用科学计数法写为另一种写法

转成秒:


elapsed_time / 1e6


这就很准确且易识别的转换成秒了。

Oracle的科学计数法很简单,前面是一个数字,中间跟一个e(大小写不限),后面跟一个整数(正负不限)就可以


n.nEm = n.n * 10^m


如:


1.1e1 = 1.1*10^1=11
10e6= 10 * 10^6 = 10^7 = 10,000,000
2e-2= 2 * 10^(-2)=0.02


而1e3,1e6,1e9 就正好是K/M/G或者毫/微/纳的进制转换

另外,在处理逻辑读/物理读的时候,如果希望把相关指标变成G或者M,也可以使用类似的写法。

以绝对大多数的8k块数据库而言:

标准写法是:


disk_reads*8192/1024/1024  -->转换为M
buffer_gets*8192/1024/1024/1024 -->转换成G


因为8192/1024/1024等于1/128,而128*1024约等于13万,上面的计算完全可以改写为


disk_reads/128
buffer_gets/13e4


当然,如果不是8k块大小,就不对了,需要相应调整

3个结合,就是:

...