|
先不说性能和逻辑究竟应该放在应用层还是plsql过程中这两个问题,我先说说近日遇到的一个问题:
近日发现数据库的CPU占用很高,用AWR找出Top SQL然后开始调优,但是这条语句有一个
dbms_lob.instr( userid_list , userid )
开发商把userid串接成一个字符串放在userid_list里面,userid_list是clob类型读取时默认触发 direct path read,再查I/O发现磁盘每秒读取60~70 MB,修改存储属性,让clob也能缓存在内存中,但是该死dbms_lob.instr( userid_list , userid )导致了一张一万多行的表扫描4次,一万多行不多,问题是每行都起码有一个clob(8k),估计CPU就是在这里面耗完的。
联系开发商改应用,估计拖到猴年马月,自己改又没有源代码,建索引 dbms_lob.instr( userid_list , userid ) 怎么弄?其他涉及的字段选择性及其差,都是状态字段。
现在只能说俺们机器和存储比较好,硬撑这个SQL。
如果对外只是提供过程作为接口,那好办,方法多了,废掉这个表,把userid_list拆开按照范式做,建立相应的索引,用userid查,那根本就不是什么难调的SQL;不改表,在这个表加触发器,增删改都修改另一个范式的 userids 表,再改SQL把dbms_lob.instr( userid_list , userid ) 改成搜索遵守范式的表;再不行,上全文索引,把dbms_lob.instr( userid_list , userid )改成 contains(userid_list , userid);
方法多的是,把过程或者SQL放在数据库一级关键是实现了接口与具体实现的分离,深奥一点的说法是,用接口把调用和具体实现隔离,GOF的设计模式中很多都是在实现变与不变的分离,策略模式,模板方法模式,工厂模式等等就是最好的例子。
再说远一点,贪方便把SQL放在页面或者应用中开发速度是快,ASP年代MS也是这么想的,自从JSP崛起,以及ASP.net哪一个不是搞分层?
层与层之间的调用哪个不是通过接口隔开,不用接口隔开就和一堆类调用另一堆那样,最后变成一碗兰州拉面一样。
说回刚才那件事,现在的状况就是应用对于DBA来说就是一个黑盒,接口就是那条SQL语句,你不能动,只能动数据的一些存储结构,例如索引,表类型等,处处受限。 |
|