Kaya发表于os2ora.com PL/SQL是Oracle对SQL的过程化扩展,是Oracle数据库内部直接支持的语言。甚至,管理数据库的API接口都是以PL/SQL存储过程的方式提供的,耳熟能详的诸如收集统计信息,打印执行计划等等。 PL/SQL除了与SQL语言无缝衔接之外,还具有所有过程化强类型语言的一切特征,如变量/过程/函数的定义,一般的控制结构,异常处理等等。很多生产系统上也普遍使用着PL/SQL,这有两类场景。 第一类场景,PL/SQL的作用主要是把一系列的统计分析类型的SQL串起来,这中间会用到一些中间表做为数据处理的过渡。系统的主要执行时间主要还是花在SQL的执行上。 另一类场景,PL/SQL的作用在于对数据进行处理,使用游标从数据库中获取数据,之后使用PL/SQL的循环结构依次处理每行记录。当然,为了提高性能,一般会用到bulk批量操作。 在买了强劲的机器后,一般大家就开始对这两类场景进行优化。结果是显而易见的,不管第二类场景如何优化,系统的性能就是上不去,而把第二类场景使用第一类场景的方法重写后,性能一般就会有成百上千倍的提升。 从中得到的一个结论就是,能够使用SQL完成的事情,就不要自己通过过程化语言(Java和PL/SQL本质上是一样的)实现。SQL引擎是一个数据库最核心的部件,要好好加以利用。SQL语法无比强大,很多数据转换逻辑可以通过下面的技术通过SQL加以实现: 集合操作minus, intersect 半连接,反连接exists, not exists 窗口函数 多表插入 外连接 分析函数 PL/SQL函数 等等 当然,PL/SQL也有其重要的作用,比如前面提到的,很多管理数据库的接口都以PL/SQL的方式提供。另外,很多对数据库的监控工具也都使用PL/SQL部署在数据库内部。这很容易理解,打个类比,为了监控操作系统的性能,一种方法是把监控脚本直接部署在被监控的主机上,另一种是通过网络定时登录到被监控主机上执行监控命令。第一种方式的效率当然会比第二种方式高,它避免了每次的登录开销,还有,可以更加精确地对性能计数器的数据进行统计,如求平均值。平均值等于两个时刻的计数器值的差除以两个时刻之间的间隔,当然,时刻的表示最好与性能计数器在同个服务器上。监控数据库是一样的原理,直接运行在数据库内部的PL/SQL对数据库的监控会有得天独厚的优势。 值得推荐的以PL/SQL写就的一个性能监控分析工具是Tanel所写的Session Snapper。 Snapper is meant to be a quick and easy ad-hoc performance troubleshooting tool for the field-DBAs out there who…
SQL的那些事儿
Kaya 发表于os2ora.com SQL于数据库工程师,是最主要和最重要的工作语言,没有之一。 SQL或许可以这么大致分类: OLTP场合中对响应时间要求非常苛刻的增删改查操作 OLAP场合中对大数据量进行统计分析处理的随机查询 管理维护数据库对各种内部视图的查询 还有其它很多种分类标准,如根据SQL语句的长短,执行时间的长短,访问数据量的多少。比较靠谱的应该是所要访问数据量的多少,如果访问数据量占全表比例比较少,应该考虑索引访问,这一般是OLTP类型的SQL;如果访问数据量占全表比例比较大,应该考虑全表扫描,这一般是数据仓库类型的系统。 SQL的执行是数据库中最主要的部分,而其中最重要的当属执行计划的生成。执行计划的好坏影响着SQL的性能,进一步响应整个系统的性能。可以说,数据库的性能,归根到底就是SQL的性能。 执行计划的生成,由优化器负责。粗略地讲,主要包括两方面,第一是对数据表的访问方式,如全表扫描、索引访问。第二是多表之间的连接方式,如嵌套循环、Hash连接、排序合并等等。如何决定这两个方面的选择,9i之前的Oracle采用的是基于规则的优化器(RBO),9i之后则使用的是基于成本的优化器,即CBO。RBO很简单,它的根基就在于那15条规则,且规定前面规则的优先级高于后面的规则。 RBO Path 1: Single Row by Rowid RBO Path 2: Single Row by Cluster Join RBO Path 3: Single Row by Hash Cluster Key with Unique or Primary Key RBO…
C的那些事儿
kaya发表于os2ora.com C语言于我,主要是一门学习性的语言,这或许也是大多数人第一门接触到的计算机语言。当然时代在变,现在的学生也不一定要从C语言学起啦。C语言在Linux的世界有着举足轻重的地位。Linux内核是用C写的,Linux上的大部分应用也是用C写的。关键是,它们都是开源的!于是,如果你想进一步提高C语言的品味,Linux开源世界真的是海阔凭鱼跃,天高任鸟飞了。 C语言应该是最接近硬件底层的高级语言,可以很透明地操作任何硬件资源,如CPU/IO/内存等等,这使得它成为最理想的系统编程语言,包括对系统性能要求很苛刻的产品,如各种操作系统,数据库,播放器等等。 Linux无疑是谈论C语言的最佳场合。学过操作系统的人对Linux的C函数接口应该都不会陌生,如各种open, printf, pipe, fork, memset等等。我手头就有一本Linux C函数手册,不厚就两三百页,每个函数后面都有一个小例子演示其用法,它真是编写Linux上C程序的居家必备参考手册。 或许还应该提一下阅读C代码的一个利器,Source In Sight。它支持很多功能,如代码跳转,多功能搜索,函数、类、变量之间的各种关系图,文件列表等众多功能。Source In Sight给自己的一个自画像如下: 在Linux世界浩瀚的代码中,Source In Sight会让你少迷失点方向。 当然,Source In Sight给你的,也只是对代码的一个静态理解,里面有太多自己对代码运行的一厢情愿的假设,还有对代码运行的未知的迷惑。我更推荐的,当然是在代码运行时,生成各种函数之间真实的调用图,最好再明白告诉每个函数被调用的次数及执行时所占时间的百分比。这就是Linux下的一个很出名的工具:gprof。为了在一个程序上使用 gprof, 必须在编译程序时加上 -pg 选项 ,在程序运行时产生gmon.out文件。假设程序名为test。则执行下面语句,gprof ./test gmon.out,生成的输出会列出这个程序中每个函数被调用的次数、所花费的时间等各方面信息,当然还有函数之间的调用关系。 不过,gprof的输出是文本的,不大直观,可使用另一个工具对gprof的输出结果进行处理,形成函数调用关系图。这个工具就是cgprof。执行cgprof –Tps gprof.out > result.ps,再利用如Acrobat Distiller之类的工具,加工result.ps就可以得到函数调用图result.pdf文件。当然,cgprof也提供选项以直接在X Winow下面生成调用图。下图就是一个生成的函数调用关系图的例子: C语言的可读性与维护性历来得不到什么好评,但由它所写成的程序却流传广泛,深入人心,如各种视频编解码模块,文本处理工具awk/sed等等。这或许应该得益于Linux平台的优雅的设计。这里最想提到的,就是Linux的管道功能,管道使得多个应用程序间可以无缝衔接,从而达到代码复用的目的。代码复用的第一个层次应该是C语言语句级的复用,如很多开源项目都是建立在更多的开源项目基础上;而代码利用的第二个层次就是二进制的复用,包括以类库的形式和以可执行文件的形式。Linux神奇的地方在于可以让以可执行文件形式的复用神不知鬼不觉地进行。比如,如果想实现对输出文件的压缩,只要把输出文件指定为FIFO管道文件,让程序往FIFO文件里写,再启动一些gzip进程,从管道中进行读取,边压缩边写回文件系统就行了。还比如,平常通过用grep,awk,xargs等等命令通过管道符|串起来的那一长串命令。想想在GUI环境下的一个单一程序中实现这些功能会是多么艰难的事情啊!
Java的那些事儿
Kaya 发表于os2ora.com Java于我,是一门很实用的语言。在大学里,起码在我们那时的大学,Java可不是一门登堂入室的语言,那是汇编语言,C语言,甚至Pascal语言的天下。不过Java却是学生时代兼职的第一语言(嘿嘿,真实用)。这对大学的语言教学真有那么一点讽刺意味。 当然,我觉得相比C/C++,Java做为后起之秀,吸取着以前语言的经验教训,而又没有类似C++必须兼容C的沉重负担,一切从新设计,这使它变成了一门简单而又强大的语言。还有,Java有着丰富的入门教程,新手很容易通过例子掌握一个具体的知识点。Java的IDE应该是做得比较出色的,如JBuilder,JDeveloper,Eclipse。 而正式工作后,在实际项目中使用C/C++的机会其实也很少,这是一个开发效率的问题,虽说C/C++的运行效率比Java更高,但现在人们更关注的,却是开发效率,还有应用总体的高性能与高可扩展性问题。对于开发并发应用,Java提供了内置的支持,而C/C++,线程安全,并发技术,对于一般的入门者那应该是很高阶的话题吧。 当然,Java的易于上手,并不表明新手们就能把它用得很好。例如,对于与数据库打交道,没有对数据库的基础知识那也是不行的,对于Java来说,很大一部分就在于如何使用JDBC开发出高性能的数据库Java应用程序。这里当然可以推而广之,对于其它的编程语言,这一问题也广泛存在,如如何使用OCI开发高性能的数据库C应用程序,Pro*C应用程序,PHP应用程序。 对于Oracle数据库而言,起码有以下几点是Java程序员所应该掌握的: 第一是连接池技术,数据库默认就提供了对高并发的支持。应用程序有两种极端,一种是全局只使用一个连接,这很幼稚,但这确实存在;另一种是只要需要操作数据库,就创建一个新的连接,从而会出现同一时刻,并发数据库连接数成千上万的情形。解决以上两种问题的方法就是使用连接池技术,并设置一个合理的连接数的最大值,这取决于数据库服务器的CPU个数,最佳的连接数一般应该在CPU个数的2到4倍左右。 UCP是Oracle提供的连接池驱动,以ucp.jar的形式提供。一个简单的示例如下: 如果不用连接池,就不需要上面的ucp.jar,只需要一般的驱动,如ojdbc5.jar。 第二是语句池技术,解析SQL语句并生成执行计划,对于数据库引擎来说是很昂贵的操作。因此,在SQL语句中必须使用绑定变量而不是文本常量。另一方面,即使通过绑定变量避免了重新生成执行计划,但如果还存在软解析也会给系统带来额外的CPU消耗。如下面的语句: 每执行一次conn.prepareStatement都会导致数据库里的一次软解析。解决方法有三种: 1. 把这个conn.prepareStatement移动while循环的外面。 2. 对于直接从DataSource获取的连接,启用连接的语句缓冲。 3. 而对于UCP连接池,则可以通过设置连接池的属性启用语句的缓冲。 第三是各种泄露问题,连接泄露,语句游标泄露,锁泄露。Java语言只会帮助回收应用程序里的内存结构,却不会帮助你关闭曾经打开的数据库连接、游标,以及对事务的提交或回滚。下图是一个演示锁泄露的例子,粉红色区域面积越来越大,代表等待事件enq: TX – row lock contention越来越严重。一个常见的原因就是异常处理的代码中忘了对事务进行commit或者rolloback。
PERL的那些事儿
Kaya 发表于os2ora.com PERL是Practical Extraction and Report Language的缩写,或许它的主要特点就是Practical。我想大部分人不会主动去接触这种语言,PERL脚本读起来不就是破脚本么,听说在英文里也是Pathologically Eclectic Rubbish Lister(病态折中式垃圾列表器)的缩写呢!除非真地发现了它的可取之处,否则大家对它都会敬而远之吧。 对于我而言,Shell语言对于日常工作基本已可应付。只是有一天,我想写点socket编程,但是又不想使用Java那些必须编译的语言。PERL第一次进入了我的视野。当然,最终采写PERL的原因还在于socket编程的另一端(服务器端)本身就是用PERL语言写的,客户端用PERL也就成了理所当然顺理成章的事情了。 当然,对PERL的熟悉还来自于对开源的以PERL语言写成的Linux系统监控软件collectl源代码的阅读和改动(以适应对Exadata上的Flash I/O的监控)。 对于熟悉C语言的程序员来说,阅读PERL脚本应该是没有问题的。它基本填补了Shell语言与高级语言之间的空白,结合了两者的优点,即有Shell语言的方便易用免编译,又拥有类似高级语言的丰富的类库。 我觉得PERL语言对于代码简洁的追求简直到了某种病态的程度。举几个日常用到的例子吧: 有一行以空格分隔的由多个列组成的文本,我们想知道每个列所对应的索引。如对于下面一行: OWNER OBJECT_NAME SUBOBJECT_NAME STATUS 列OWNER的索引为0,OBJECT_NAME索引为1,SUBOBJECT_NAME的索引为2,STATUS的索引为3。 Java语言的实现可以是: 之后可以通过map.get(“STATUS”)得到STATUS的索引值。 PERL的实现可以是: PERL中以@开头的变量代表数组,$开头的变量代表标量,以%开头的变量代表哈希。$_代表具体场合下的一个标量值,如在这里,代表0到最后一个元素索引值(0..$#array)之间的一个值。$#代表数组最后一个元素的索引值。 于是上面第一行PERL语句的意思就是把$row进行分割,分割后的元素放到数组array中。 第二行的意思就是针对数组的所有索引值0到$#array,把索引值对应的列名及索引值本身存入到哈希变量indexed中。 之后就可以通过$indexed{‘STATUS’}得到STATUS的索引值了。 第二个例子是指定两个数字,输出这两个数字之间的所有数字,并保存在数组。如指定1和4,则输出1,2,3,4。 相应的PERL代码为: eval为动态执行括号里面的语句,有点像PL/SQL里面用EXECUTE IMMEDIATE执行动态SQL语句。 PERL中利用.号实现字符串间的拼接,上面括号里通过赋值后其实就是:map { $_ } 1..4 这个语句用到的map上面已经讲过,就是把后面1..4每个值进行大括号里的运算,并返回,这里我们只要简单的返回就可以了。于是,最后数组@s里面就保存着1,2,3,4这四个值了。 很变态,又很简单,对否? 当然,提到PERL,不可能不提它对文本的高效处理。下面是第三个例子:…
Shell的那些事儿
Kaya 发表于os2ora.com 日常工作中,哪种语言对你的帮助最大?我觉得非Shell莫属。最早接触Shell应该是在大学的时候,如做Linux文件系统裁减会用到一些命令,如find, tar, xargs, cp等等,并把它们通过SHELL组合起来。但现实项目中最早接触到Shell脚本,其实是Windows的批处理脚本,BAT脚本被用于在EFI测试过程中的自动化测试。那真是一套庞大的脚本,也是对学生时代的一个冲击。 毕业后开始工作时,工作环境主要还是在Linux下面,不可避免地会用上各种命令,并尝试着用这些命令解决一些实际问题,如递归列举出当前目录下所有的文本文件,当系统浏览完grep的man文档后,其实只需要一条命令,如你想知道/bin目录下是否有些命令是简单的Shell脚本而已: -I用于指定不匹配任何二进制文件,-r递归搜索子目录,-l当匹配上一行时打印文件名而跳过当前文件,因为我们提供的匹配是个万能匹配,因此所有可能的非空文本文件就都被列举出来了。 还比如,想统计一下最近编写了多少行代码: 当然,偶尔还会用用AWK或者SED,如把上面的命令重写一遍,自己实现后面的累计功能: 后来,加入Real-World Performance Group后,写脚本的干劲一发不可收拾。这主要归功于日常项目对Shell的强势需求,还有一班对Shell非常精通的外国同事。一些以前没用到的实用功能开始变成工作习惯。最实用的一个功能,莫过于如何定位BASH脚本的错误。调试选项-x可以打印出整个Shell脚本的执行过程,这个选项在脚本编写过程发挥了巨大的作用。还有如何给参数设置默认值,如何利用set动态处理数组。同时,还学到了很多利用Shell编写项目实际案例业务逻辑的方法。如如何实现多进程并发和排队,当某进程完成后,排队队列中的第一个进程得到机会继续运行。 回过头来,Shell语言的设计初衷或者就是实用方便快捷,有些时候可能给人以不严谨的感觉。不像C语句,回车与否会影响到Shell语句的解析。如 if 语句起码有以下三种形式: 一行代码基本等于一行语句,如果想在一行包含多个语句,就必须用;分隔,懂得了这一点,你就不会漏掉某些分号或者多添加一些不必要的分号了。 还有,condltion其实可以是一个命令,根据命令的成功与否决定是否执行相应的命令,看起来是非常方便的设计,如 当然,可以利用命令的返回值$?做判断,成功时$? 的值将为0: 当然,上面的逻辑可以简单用&&实现: 相对于高级语句如C/C++/Java,Shell其实应该是一门最容易上手,也能够给工作带来最大便利的工具性语言,无论是写写程序做下并发的压力测试,还是实现比较复杂的控制逻辑,Shell语句的开发效率一般都比那些高级语言要高,不需要编译,一写完马上可以测试。在这个追求效率的年代,不熟悉Shell都不好意思说会性能调优啊。
Javascript的那些事儿
Kaya 发表于os2ora.com 目前最流行的语言是哪一种?或许是Javascript。做为一种前端语言,Javascript这几年得到了很长足的发展,AJAX或许是它发展的一个里程碑。Firefox与Chrome等现代浏览器的流行,更使得Javascript的开发效率大大提升。另一方面,Web应用的蓬勃发展,也使得Javascript编程的市场极大。 前端技术的发展,把美工设计与逻辑实现相分离,之前把Javascript嵌入到HTML代码中的日子一去不复返了,一整个项目,都是由Javascript构成,这在之前的时代是多么不可想像的事情。不过,在众多Javascript类库的支持下,这一梦想其实早就成为现实了。程序员们也终于可以利用Javascript当一个纯粹的程序员,不掺一点美工的。 我们或许可以从Javascript如何为数据库监控服务做为切入点聊聊这个语言。 10g以后,EM中的等待事件图应该是最受欢迎的也被使用最多的一个功能,下面是一个例子: 如何自己利用Javascript显示上面的图形呢? 当然,我们需要有一个Javascript的图形库,把划图的工作交给它,做为DBA的我们要知道的是如何获取数据源,如何转换数据以交给图形库显示。 图形库,我推荐用ExtJS中的相应组件。ExtJS是一个非常值得使用的Javascript类库,拥有极其丰富的例子和文档,基本上UI设计中的所有元素都可以从这些例子中找到踪迹,进而利用这些例子,实现自己业务逻辑的展现。例如,和上图EM中的等待事件图类似的例子: 相应的源代码看起来非常简洁呢: store1存储的就是用来显示的数据,data是一个数组,里面有12行记录,每行对应一个月份,name即为月份的名字,其它的data1到data9代表该月份不同种类(如等待事件)的值。 那么回到等待事件图,如何动态给图形提供数据呢?显然,每隔一个时间间隔,如5秒,我们会从数据库获取一行新的记录,把它存放进store1中,同时,删除store1中的最旧的一行记录,以此就可以实现图形的动态前移了。 Javascript做为一门动态语言,对数据操纵的灵活性在这里得到了极大的展示,如上面逻辑对应的基本代码为: 在这里,对比一下Java和Javascript这两种语言或许是很有趣的事情。想想如何使用Java去实现上面的逻辑?首先,Java中类的属性是不能动态定义的,于是你需要定义一个记录类,里面是诸如time,total,on_cpu这些属性。其次,Java中属性的名字是不能包含空格的,于是你需要为”ON CPU”定义一个类似on_cpu的变量名。还有,你不能方便地遍历一个类里面的所有属性,于是只能把上面的那个循环写成9行类似下面的语句: item.time=xxx; item.total=xxx; 看起来Java的代码比Javascripts臃肿多了。 写到这,再顺便一提,Javascript中类的属性可以动态定义,体现在item['time']这种写法其实等价于Java程序员非常熟悉的写法item.time。习惯了Java的语法,看到这种形式一定会感觉特别新鲜。这也许是Java和Javascript的一个最显著的区别。 继续说说如何从Oracle数据库中得到这些等待事件类别对应的数值(active session number)。相应的查询语句如下: 当然,这里统计的粒度其实是等待事件,而不是等待事件类别,Javascript代码中还需要对其做进一步做汇总,才能给上面的图形提供数据,不过,这带来一个好处,有了这些等待事件的信息,我们可以在合适的时候加以展示,例如,当鼠标移到某一时刻时,显示这一时刻看对应的所有等待事件的比例图。当鼠标再次移动某个等待事件上时,只显示出这个等待事件的趋势图。 下面就是最终的一个效果图: Javascript或许是被低估的一门语言。在WEB流行的时代,学学javascript是一个很酷的事情。
Mac下面Oracle环境的各种折腾
Kaya 发表于os2ora.com 首先,我们需要有一个Oracle Database。通过网络远程登陆到公司服务器总不是一件靠谱的事情,特别是出差途中,客户现场时。不过这个比较容易满足,装一个虚拟机软件,在其上面安装一下Linux,在Linux下面安装Oracle数据库就搞定了。虚拟机软件有很多选择,如Oracle VirtualBox, Vmware等等。然后就是安装Linux操作系统,Oracle数据库这些按部就班的事情啦。不过虚拟机有个好处,当完成Oracle的安装后,可以对整个虚拟机文件打个压缩包,之后哪一天数据库或者Linux坏掉了,只要简单地解压缩就得到了一个全新的可运行的数据库了。 为啥不在Mac上面直接安装Oracle?其一,Linux安装Oracle比较接近真正的生产环境,就如Windows下面较少运行Oracle一样。其二,在Mac上面运行虚拟机的速度其实挺快。其三,虚拟机可以避免Oracle对Mac的可能的破坏。 接下来是配置好客户端对数据库的访问,登陆到服务器上(虚拟机或者真正的远程服务器)未尝不可,不过有时还是希望在Mac上使用客户端软件,如SQL Developer,或者自己开发的Java 程序。 SQL Developer直接从Oracle网站下载就可以了,根本不需要自己再配置数据库驱动等。 而一般的Java连接,对应thin连接只需要在classpath中添加一个简单的jar包如ojdbc5.jar。对于oci连接,需要相应的库文件,这可以通过使用instance client实现。 Instant Client allows you to run your applications without installing the standard Oracle client or having an ORACLE_HOME. OCI, OCCI, Pro*C, ODBC, and JDBC applications work without modification,…
Oracle 11g Database Resource Manager (2)
Kaya 发表于 os2ora.com 数据库资源管理模型主要由数据库资源计划(Plan),使用者组(Consumer Group,CG),计划指令(Directive)组成。一个Plan 对应多个CG,而一个CG对应多个指令。数据库会话通过映射规则(mapping rules)映射到相应的CG上。计划指令是资源管理最核心的东西,它对CG对资源的使用进行定义和分配。根据官方文档,计划指令实现的对资源的管理包括: CPU Degree of Parallelism Limit Parallel Statement Queuing Active Session Pool with Queuing Automatic Consumer Group Switching based on resource criteria Canceling SQL and Terminating Sessions based on the amount of system resources…
Exadata:存储节点上所有监控指标与其监控概览
Kaya 发表于 os2ora.com CellCLI是Exadata上存储节点的一个命令,是管理和监控存储节点的一个重要接口。例如,可以通过它收集各种指标(metric)和警报(alert)。了解这些指标的一个好方法是通过CELLCLI命令,从中挖掘出最新的信息。 可以通过以下命令得到存储节点所支持的所有指标: list METRICDEFINITION attributes objectType,metricType,Name,UNIT,description 稍做整理,可以得到下面的表格: objectType metricType Name UNIT description CELL Instantaneous CL_BBU_CHARGE % Disk Controller Battery Charge CELL Instantaneous CL_BBU_TEMP C Disk Controller Battery Temperature CELL Instantaneous CL_CPUT % Percentage of time over the…