楼主: yulihua49

[PRO*C] 看我做的数据库包装器

[复制链接]
论坛徽章:
14
2009新春纪念徽章
日期:2009-01-04 14:52:28沸羊羊
日期:2015-03-04 14:51:52优秀写手
日期:2014-03-14 06:00:13马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15蜘蛛蛋
日期:2012-06-27 21:08:142012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26
231#
 楼主| 发表于 2009-2-19 13:06 | 只看该作者
原帖由 newkid 于 2009-2-18 23:41 发表


你让我怎么说呢?OCI只是个和数据库引擎打交道的接口,PLSQL的底层也是OCI.
而隐性游标是PLSQL提高的高一层的功能,它会利用OCI去自动打开游标、绑定、执行、FETCH、根据需要决定是否关闭。
PLSQL程序员只需要写SQL就行了,典型的如:
SELECT ...
  INTO 变量
  FROM ....

其他的根本不要操心。这就是一个隐性游标。
其他语言没有这功能,因此使用SQL没有那么方便,从而造成了程序员不喜欢甚至害怕使用SQL。

你可以说PLSQL也是一个包装器,但它和你的包装器截然相反:它鼓励使用SQL, 为使用SQL提供了很多便利。

如果你的排序比SQL快,那肯定不是ORACLE数据库,要不你就试试。我和你恰恰相反,有时候我的数据在内存中不在表中,我也宁愿写几行SQL进行排序而不愿自己做。

那就是说,DAU还是为OCI用户做了点好事,帮助他们保持游标和bind区.
那么,PRO*C呢?那可是OCI的简易包装,没增加什么功能,好象简化了bind,但只支持具名bind,如果不知道变量就没辙了.如果动态语句,就和OCI一样的烦琐.
怪异问题已经追踪到OCI里边去了,不是包装器的问题,但是包装器可以很简单的写一个通用的dummy_update把这个问题轻易化解.
但愿是ORACLE这个版本的问题,希望以后能解决.

[ 本帖最后由 yulihua49 于 2009-2-19 13:14 编辑 ]

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
232#
发表于 2009-2-20 02:32 | 只看该作者
原帖由 yulihua49 于 2009-2-19 13:06 发表

那就是说,DAU还是为OCI用户做了点好事,帮助他们保持游标和bind区.
那么,PRO*C呢?那可是OCI的简易包装,没增加什么功能,好象简化了bind,但只支持具名bind,如果不知道变量就没辙了.如果动态语句,就和OCI一样的烦琐.
怪异问题已经追踪到OCI里边去了,不是包装器的问题,但是包装器可以很简单的写一个通用的dummy_update把这个问题轻易化解.
但愿是ORACLE这个版本的问题,希望以后能解决.


我对那些饱受煎熬的C程序员的建议是:
把你们的聪明才智和宝贵时间用来学习SQL和PLSQL编程;把原来的程序尽量移植到存储过程中,C代码越少越好。
如果寄希望于某个包装器能够摆脱SQL,那么你就写不出高效访问数据库的代码,永远掌握不了数据库应用的精髓。

对于这个UPDATE提速的现象,我一直怀疑你没有执行到INSERT出错的部分,因为一旦出错时间就会倍增。
为了证明这一点,我们可以加一个简单的计数器。

环境设置:

CREATE TABLE tjrb_test_log (cnt NUMBER);

INSERT INTO tjrb_test_log VALUES (0);

COMMIT;

CREATE OR REPLACE TRIGGER tjrb_ins BEFORE INSERT ON tjrb FOR EACH ROW
DECLARE
   PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
   UPDATE tjrb_test_log SET cnt = cnt+1;
   COMMIT;
END;
/
这样每次INSERT, 不管成功与否,计数器都会递增。多了这个触发器当然会使得你的UPDATE和INSERT比原来略慢,但是有助于我们发现问题。

当你每次开始一轮新的实验之前,先把计数器清空:

UPDATE tjrb_test_log SET cnt=0;
COMMIT;

现在需要你做的实验时:
先让表中装载数据(为了让第二次出错);
清空计数器;
执行你的“提速”代码;
SELECT * FROM tjrb_test_log;
这样可以清楚地看到,在你的提速UPDATE之前是不是真的发生了7552次INSERT?

使用道具 举报

回复
论坛徽章:
14
2009新春纪念徽章
日期:2009-01-04 14:52:28沸羊羊
日期:2015-03-04 14:51:52优秀写手
日期:2014-03-14 06:00:13马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15蜘蛛蛋
日期:2012-06-27 21:08:142012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26
233#
 楼主| 发表于 2009-2-20 11:57 | 只看该作者
原帖由 newkid 于 2009-2-20 02:32 发表


我对那些饱受煎熬的C程序员的建议是:
把你们的聪明才智和宝贵时间用来学习SQL和PLSQL编程;把原来的程序尽量移植到存储过程中,C代码越少越好。
如果寄希望于某个包装器能够摆脱SQL,那么你就写不出高效访问数据库的代码,永远掌握不了数据库应用的精髓。

对于这个UPDATE提速的现象,我一直怀疑你没有执行到INSERT出错的部分,因为一旦出错时间就会倍增。
为了证明这一点,我们可以加一个简单的计数器。

环境设置:

CREATE TABLE tjrb_test_log (cnt NUMBER);

INSERT INTO tjrb_test_log VALUES (0);

COMMIT;

CREATE OR REPLACE TRIGGER tjrb_ins BEFORE INSERT ON tjrb FOR EACH ROW
DECLARE
   PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
   UPDATE tjrb_test_log SET cnt = cnt+1;
   COMMIT;
END;
/
这样每次INSERT, 不管成功与否,计数器都会递增。多了这个触发器当然会使得你的UPDATE和INSERT比原来略慢,但是有助于我们发现问题。

当你每次开始一轮新的实验之前,先把计数器清空:

UPDATE tjrb_test_log SET cnt=0;
COMMIT;

现在需要你做的实验时:
先让表中装载数据(为了让第二次出错);
清空计数器;
执行你的“提速”代码;
SELECT * FROM tjrb_test_log;
这样可以清楚地看到,在你的提速UPDATE之前是不是真的发生了7552次INSERT?

我对那些饱受煎熬的C程序员的建议是:
把你们的聪明才智和宝贵时间用来学习SQL和PLSQL编程;把原来的程序尽量移植到存储过程中,C代码越少越好。
如果寄希望于某个包装器能够摆脱SQL,那么你就写不出高效访问数据库的代码,永远掌握不了数据库应用的精髓。

业务逻辑一旦变更,一群程序员会发疯的。再说,我这个包装器效率很高啊,而且还能把负载分担到中间服务器。看我前边的时间统计,所有user、sys时间都是在应用服务器开销的,极大减轻数据库服务器的压力。
看现在这个程序,多舒服,就如Hibernate说的,“优雅的程序”,数据结构修改一点不用着急(修改好几次了),而且速度一点不慢。
/* 席位申请 接收格式:
        reqst="上车日期|全车次|上车站略码|下车站顺号|席别|用途|数量|"
           返回结果在result中,JSON对象。被送到客户端。

*/

int getxw(GDA *ctx,char *reqst,JSON_OBJECT result,char *msg)
{
int ret,i;
INT64 now;
SEAT_stu seat;
T_PkgType seat_sub_tpl[6];
struct mkseat_stu app;
DAU seat_DAU,seat_sub_DAU;
JSON_OBJECT json_array;
SRM app_SRM;

        if(!msg||!result) return -1;
        now=now_sec();
        *msg=0;
        SRM_init(&app_SRM,0,&app,mkseat_tpl);
        SRM_dispack(&app_SRM,reqst); //拆包
        DAU_init(&seat_DAU,ctx->SQL_Connect,0,&seat,SEAT_tpl);
        //生成子模板,一共就涉及了这5个字段,只要不删除这5个,其他随便改,与本程序无关。
        partt_copy(seat_sub_tpl,SEAT_tpl,"flag, used_dev, used_uid, used_time, ROWID");
        DAU_init(&seat_sub_DAU,ctx->SQL_Connect,0,&seat,seat_sub_tpl);
        ret=SRM_copy(&seat_DAU.srm,&app_SRM,0);//检索条件装入seat_DAU

        if(0!=getSeat_for_sell(&seat_DAU,app.quantity,msg)) { // seat_DAO.c
                DAU_free(&seat_DAU);
                return -1;
        }
        json_array=json_object_new_array();
        if(!json_array) {
                DAU_free(&seat_DAU);
                sprintf(msg,"getxw:Malloc json_array error");
                return MEMERR;
        }
        for(i=0;i<app.quantity;i++) {
        JSON_OBJECT json;
                if(ret=GET_NEXT_DAO(&seat_DAU)) {
                        break;
                }
                seat.flag=1;
                seat.used_time=now;
                strcpy(seat.used_uid,ctx->contex.userid);
                strcpy(seat.used_dev,ctx->contex.devid);
                ret=updateSeat_by_ROWID(&seat_sub_DAU,msg);//seat_DAO.c
                if(ret != 1) {
                        ShowLog(1,"占用席位失败,stmt=%s,ROWID=%s", msg,seat.ROWID);
                        i--;
                        continue;
                }

                seat.end_station = app.arrive;
/* 结果打JSON包 */
                json = json_object_new_object();
                if(!json) MERR_RET
                DAU_toJSON(&seat_DAU,json,0);
                json_object_array_add(json_array,json);
        }

        DAU_free(&seat_DAU);
        if(i==0) {
                ctx->SQL_Connect->Errno=SQLNOTFOUND;
                return 0;
        }
        json_object_object_add(result,"seat_data",json_array);
        return i;
}
我们已经辩论这么久了,为什么时至今日你还主观断言包装器一定低效呢?低效不低效,要看水平,所以我的题目叫“ 看我做的数据库包装器”如何。
这不完全是我的水平,你也有一份。就像自动档的车,老师傅看不起,其实做好了也费不了多少油,对于新手来说,并不比笨手笨脚的开手动档费。
这个程序,你也可以理解为C的存储过程,实际对客户端而言就是这么回事。这个程序没比谁慢哦!经初步测试,比IBM的TPF要快很多倍哦!
http://www-01.ibm.com/software/htp/tpf/

插入动作肯定是完成了,错误信息都出来了。唯一键约束违例,只不过我没打日志,故意不打的,太多。

loadasc:load 0 rec's time=6,buf=bind_ins:sqlo_execute=-1,errmsg=ORA-00001: unique constraint (TICKET.SYS_C0011534) violated,tabneme=tjrb,
bind=1:tjdate=2006.01.31,2:unit=55,3:tabname=A7,4:flg=102,5:dat1=0,6:dat2=0,7:dat3=0,8:dat4=0,9:dat5=0,10:dat6=0,11:dat7=0,
12:dat8=0,13:dat9=0,14:dat10=0,15:dat11=0,16:dat12=0,17:dat13=0,18:dat14=0,19:dat15=0,20:dat16=0,21:dat17=0,22:dat18=0,
23:dat19=0,24:dat20=0,25:dat21=0,26:dat22=0,27:dat23=0,28:dat24=0,29:dat25=0,30:dat26=0,31:dat27=0,32:dat28=0,33:dat29=0,
34:dat30=0,35:dat31=0,36:dat32=0,37:dat33=0,38:dat34=0,39:dat35=0,40:dat36=0,41:dat37=0,42:dat38=0,43:dat39=0,44:dat40=0,
45:dat41=0,46:dat42=0,47:dat43=0,48:dat44=0,49:dat45=0,50:dat46=0,51:dat47=0,52:dat48=0,53:dat49=0,54:dat50=0,
按你说的,把bind值打出来。这是最后一条记录。如果是第一条,有一个insert语句,后来的都没有了。

[ 本帖最后由 yulihua49 于 2009-2-20 17:11 编辑 ]

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
234#
发表于 2009-2-21 01:47 | 只看该作者
"业务逻辑一旦变更,一群程序员会发疯的。"
神经这么脆弱就别当程序员了。如果你模块化分工做得好,业务变更只需修改相应的模块,有什么好担心的?用了你的包装器难道就什么都不用改了?


"再说,我这个包装器效率很高啊,而且还能把负载分担到中间服务器。看我前边的时间统计,所有user、sys时间都是在应用服务器开销的,极大减轻数据库服务器的压力。"
你前面的加载数据例子是简单的INSERT, 这个售票也是简单的单表操作,体现不出事务的复杂性。“所有user、sys时间都是在应用服务器开销的”,那是因为ORACLE很牛B。


“看现在这个程序,多舒服,就如Hibernate说的,优雅的程序”
审美话题,情人眼里出西施。


“数据结构修改一点不用着急(修改好几次了)”
如果你这个模块需要的输出字段没有变,那么修改数据结构就不会影响到接口。你这样不管3721全部SELECT *, 我是不以为然的。
再说你这个模块的重头在getSeat_for_sell, 至于外面这一层,是轻量级的,顺手就随便做了,也不用特意分给其他级别的程序员。

"我们已经辩论这么久了,为什么时至今日你还主观断言包装器一定低效呢?低效不低效,要看水平,所以我的题目叫“看我做的数据库包装器”如何。"
我一开始就说“大部分自动产生的SQL都是垃圾”,这话有些伤人,换个温和的说法是“自动产生的SQL不是最好的”,而且它会让程序员产生定势思维,停止寻求更好的解决问题的办法。

"就像自动档的车,老师傅看不起,其实做好了也费不了多少油,对于新手来说,并不比笨手笨脚的开手动档费。"
PLSQL编程一点也不难,它就是友好的自动档的车。直接用OCI编程可算是手动档。
TOM前辈精通PLSQL和C语言编程,在他看来PLSQL比C更容易掌握,生产率更高,我同意他的看法。

"这个程序,你也可以理解为C的存储过程,实际对客户端而言就是这么回事。"
可以这么说,但是如同上述,我认为PLSQL来做存储过程生产率更高。

"这个程序没比谁慢哦!经初步测试,比IBM的TPF要快很多倍哦!"
哪个程序?数据加载的?

"插入动作肯定是完成了,错误信息都出来了。唯一键约束违例,只不过我没打日志,故意不打的,太多。"
我的计数器很简单的,拜托你就尝试一下,满足我的好奇心吧!

下面我来总结一下你认为包装器的优点,并逐一点评,(全是前面说过的话,就是汇总一下而已)
1. 速度快,本身的附加开销很小。
   如果越过你的包装器,这个优点就完全消失了。
   注意我不一定是用存储过程和你比,而是任何的我认为更好的手段。比如你的数据加载很快,但我用外部表和MERGE更快。
2. 用包装器写出来的程序优雅。
  这属于审美范畴就不点评了。
3. 程序员不用掌握SQL.
   这对程序员绝对是个损失。SQL也不是什么阳春白雪的东西,也没有高门槛,但它是访问数据库的最好手段。
   如果养成了单表访问、逐行按记录方式处理的定势思维,那么是很有害的,TOM把它称为SLOW-BY-SLOW方法(原意是ROW-BY-ROW)。
   数据库编程的最佳思维方式是集合式的,而不是单记录的。
4. 程序员即使掌握了SQL, 也不用写SQL, 在C语言中写SQL很痛苦。
   如果用PLSQL, 写SQL非常的方便,因此程序员可以用最好的SQL来完成任务。
5. 包装器会利用数据字典自动生成模板。
   这就导致了大量的SELECT *, 也不管数据是否是必需的。这在真正的高端应用中就会体现出弱势来了。
6. 如果需要手写SQL, 包装器也是支持的。
   那你还得配一个手工模板,如果用PLSQL, 写任何SQL都很方便。
7. 用包装器在C里面写逻辑处理,可以缓解数据库的压力。
   数据库是不怕你施压的。包装器不是消灭SQL, 而是自动生成SQL, 而这SQL往往不是最佳的,因此有时候反而给数据库添了麻烦,因为产生了不必要的中间数据流量。就拿前面贴子的表连接来说,包装器取出两个单表再自己作匹配,然后测试一下时间开销主要在应用服务器,就以为给数据库解了压。其实呢?你把连接用SQL实现,并不会给数据库更多开销。特别是当结果有聚合运算时,SQL出来的是分组后的计算结果,如果你试图用包装器再作分组运算,那么数据库不得不你提供大量的原始数据。
8. 必要时可以把生成的SQL打印到日志文件。
   你这开关是什么级别的?可以动态控制吗?如果我只需要看一个SQL, 会不会其他的也打印出来?
   用PLSQL编程,SQL是直接可见的,如果产生了错误数据比较容易找到源头。
9. 包装器会自动CACHE游标
   这在PLSQL中不足为奇。
   我想请教一下你们的三层结构是怎么样的?一个售票终端是否必需保持对一个应用服务器进程的连接?能否像互联网应用那样,配置若干个数据库连接来被无数的客户端共享?
10.一时想不出来,你自己凑吧。

使用道具 举报

回复
论坛徽章:
4
235#
发表于 2009-2-21 11:26 | 只看该作者
讨论这么长时间了,关注一下

使用道具 举报

回复
论坛徽章:
26
ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:44ITPUB十周年纪念徽章
日期:2011-11-01 16:20:282012新春纪念徽章
日期:2012-01-04 11:49:542013年新春福章
日期:2013-02-25 14:51:24夏利
日期:2013-08-13 23:25:29优秀写手
日期:2013-12-18 09:29:092014年新春福章
日期:2014-02-18 16:41:11马上有车
日期:2014-02-18 16:41:11蓝色妖姬
日期:2015-03-19 09:37:00ITPUB年度最佳技术原创精华奖
日期:2015-03-19 09:43:24
236#
发表于 2009-2-23 18:34 | 只看该作者
好不容易看完了,深受启发;
我基本站在 newkid  兄这边,
我的观点是:

1.pl/sql,sql是和数据库原生的打交道的;用C,java 以及一些数据访问层的框架 hibenate 等,它们和数据库的连接操作本质上也是转化成sql来执行的;效率上没法和pl/sql,sql比;
2.我们之所以用中间层,绕过看似底层的sql,可能看重的是java,c语言功能的强大性,比如OO等,但是再强大,如果应用系统是以数据库为中心的,最终兜了一圈,还是回到sql上来;
3.现在web开发确实有ejb,hibenate之类的数据访问引擎,而且很多java高手都觉得非常好;我觉得也挺有道理;楼主yulihua49 讲的也有他的道理,这些东西可能确实为开发效率提高很多,不过也许Itpub里都是搞pl/sql的较多,对一些流行的数据访问引擎也不太了解,所以更多的偏向newkid的观念;

  我个人而言,挺佩服楼主这类人才;
我更多的精力都在数据库的存储过程方面,一直把 sql,pl/sql作为“万能钥匙”;
如果像楼主那样博学,我觉得对于我们做应用系统的开发人员来说,会有更好的思路和方案;
从学习成本上来说,学习sql相对比较低的,也就是挺容易入行的;语法也不复杂;不像C#,java之类那么多概念;

我好奇一下:
楼主的C 是用纯C,不依赖于ide?直接用sqlplus就ok,也就是说直接用oracle数据库就行?
我想了解一下环境如何配置。

yulihua49

使用道具 举报

回复
论坛徽章:
14
2009新春纪念徽章
日期:2009-01-04 14:52:28沸羊羊
日期:2015-03-04 14:51:52优秀写手
日期:2014-03-14 06:00:13马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15蜘蛛蛋
日期:2012-06-27 21:08:142012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26
237#
 楼主| 发表于 2009-2-24 10:06 | 只看该作者
原帖由 qingyun 于 2009-2-23 18:34 发表


我好奇一下:
楼主的C 是用纯C,不依赖于ide?直接用sqlplus就ok,也就是说直接用oracle数据库就行?
我想了解一下环境如何配置。

yulihua49

目前是LINUX上的纯C。ORACLE是10.2.
基础是OCI,中间用了一个开源的包:sqlora,你可以在网上查一下。又包了一层自己开发的SDBC,安全数据库连接。因为安全性的要求,把数据库用户口令加密了一下,
所以数据库的打开过程比较复杂,不过使用不复杂,只要:db_open(&SQL_Connect);就行了,你没有看见任何的连接过程,都靠配置文件。数据库的口令可以任意修改,与应用无关,甚至与配置文件无关。
C语言调用SQL,不是PL/SQL,而是直接的SQL语句,可以调用存储过程(函数)。
我的意思,不是逼迫你们学C语言,而是因为某种原因,系统必须使用C语言时,提供一些方便。
框架的优越性勿容质疑,看看JAVA世界就知道了。我这个东西无人喝彩,主要原因是C语言应用太少了,就这一点用户,基本PRO*C,现在主要数据库应用都转向JAVA了。
配置文件如下:
#used by ShowLog()
HOME=/home/tuxticket
LOGFILE=$HOME/log/KP
LOGLEVEL=5
#LOGDAY=DAY

DATABASEAUTHFILE=$HOME/config/database.auth
DBLABEL=CRHKPOPER
KEYFILE=$HOME/config/KEY.txt

#logfile for sqlora8
TRACE_FILE=$HOME/log/sqlora.trc
TRACE_LEVEL=3

黑体是数据库,通过标签在ATABASEAUTHFILE里查用户、口令。
database.auth文件:
<DBLABEL CRHKPOPER>
SID=ticket
UID=oper
PWD=@wXaOnxOJCwLY
DBOWN=TICKET

<DBLABEL CRHKPQUERY>
SID=ORACLE10
UID=query
PWD=@A1Lxj_594NhC9W@@
DBOWN=TICKET
可以看到口令是加密的。将来这部分内容改到LDAP。

前边有人质疑包装器的效率,我已经用实验证明了其高效性,从理论来讲,包装器并不低效,因为他只是把需要的动作规范了一下,集成了一下,不用包装器,这些步骤也是必不可少的,你一步也省不了。在这个坛子里,我也见过OCI用户,苦恼于各种错误不知所措。当数据和操作规范化后,就不会出错,这是包装器开发程序快的重要原因:几乎不会出现操作错误。使用OCI。你必须理解每一步操作的条件、参数的概念,这太复杂了,为何不让我帮你做?
甚至包装器可以帮你提高效率,比如保留游标和bind树,连语句池都免查,提高速度2-3倍。你自己写一个保留游标的程序,很繁琐的哦!

[ 本帖最后由 yulihua49 于 2009-2-24 10:58 编辑 ]

使用道具 举报

回复
论坛徽章:
14
2009新春纪念徽章
日期:2009-01-04 14:52:28沸羊羊
日期:2015-03-04 14:51:52优秀写手
日期:2014-03-14 06:00:13马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15蜘蛛蛋
日期:2012-06-27 21:08:142012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26
238#
 楼主| 发表于 2009-2-24 10:41 | 只看该作者
原帖由 newkid 于 2009-2-21 01:47 发表
"业务逻辑一旦变更,一群程序员会发疯的。"
神经这么脆弱就别当程序员了。如果你模块化分工做得好,业务变更只需修改相应的模块,有什么好担心的?用了你的包装器难道就什么都不用改了?


"再说,我这个包装器效率很高啊,而且还能把负载分担到中间服务器。看我前边的时间统计,所有user、sys时间都是在应用服务器开销的,极大减轻数据库服务器的压力。"
你前面的加载数据例子是简单的INSERT, 这个售票也是简单的单表操作,体现不出事务的复杂性。“所有user、sys时间都是在应用服务器开销的”,那是因为ORACLE很牛B。


“看现在这个程序,多舒服,就如Hibernate说的,优雅的程序”
审美话题,情人眼里出西施。


“数据结构修改一点不用着急(修改好几次了)”
如果你这个模块需要的输出字段没有变,那么修改数据结构就不会影响到接口。你这样不管3721全部SELECT *, 我是不以为然的。
再说你这个模块的重头在getSeat_for_sell, 至于外面这一层,是轻量级的,顺手就随便做了,也不用特意分给其他级别的程序员。

"我们已经辩论这么久了,为什么时至今日你还主观断言包装器一定低效呢?低效不低效,要看水平,所以我的题目叫“看我做的数据库包装器”如何。"
我一开始就说“大部分自动产生的SQL都是垃圾”,这话有些伤人,换个温和的说法是“自动产生的SQL不是最好的”,而且它会让程序员产生定势思维,停止寻求更好的解决问题的办法。

"就像自动档的车,老师傅看不起,其实做好了也费不了多少油,对于新手来说,并不比笨手笨脚的开手动档费。"
PLSQL编程一点也不难,它就是友好的自动档的车。直接用OCI编程可算是手动档。
TOM前辈精通PLSQL和C语言编程,在他看来PLSQL比C更容易掌握,生产率更高,我同意他的看法。

"这个程序,你也可以理解为C的存储过程,实际对客户端而言就是这么回事。"
可以这么说,但是如同上述,我认为PLSQL来做存储过程生产率更高。

"这个程序没比谁慢哦!经初步测试,比IBM的TPF要快很多倍哦!"
哪个程序?数据加载的?

"插入动作肯定是完成了,错误信息都出来了。唯一键约束违例,只不过我没打日志,故意不打的,太多。"
我的计数器很简单的,拜托你就尝试一下,满足我的好奇心吧!

下面我来总结一下你认为包装器的优点,并逐一点评,(全是前面说过的话,就是汇总一下而已)
1. 速度快,本身的附加开销很小。
   如果越过你的包装器,这个优点就完全消失了。
   注意我不一定是用存储过程和你比,而是任何的我认为更好的手段。比如你的数据加载很快,但我用外部表和MERGE更快。
2. 用包装器写出来的程序优雅。
  这属于审美范畴就不点评了。
3. 程序员不用掌握SQL.
   这对程序员绝对是个损失。SQL也不是什么阳春白雪的东西,也没有高门槛,但它是访问数据库的最好手段。
   如果养成了单表访问、逐行按记录方式处理的定势思维,那么是很有害的,TOM把它称为SLOW-BY-SLOW方法(原意是ROW-BY-ROW)。
   数据库编程的最佳思维方式是集合式的,而不是单记录的。
4. 程序员即使掌握了SQL, 也不用写SQL, 在C语言中写SQL很痛苦。
   如果用PLSQL, 写SQL非常的方便,因此程序员可以用最好的SQL来完成任务。
5. 包装器会利用数据字典自动生成模板。
   这就导致了大量的SELECT *, 也不管数据是否是必需的。这在真正的高端应用中就会体现出弱势来了。
6. 如果需要手写SQL, 包装器也是支持的。
   那你还得配一个手工模板,如果用PLSQL, 写任何SQL都很方便。
7. 用包装器在C里面写逻辑处理,可以缓解数据库的压力。
   数据库是不怕你施压的。包装器不是消灭SQL, 而是自动生成SQL, 而这SQL往往不是最佳的,因此有时候反而给数据库添了麻烦,因为产生了不必要的中间数据流量。就拿前面贴子的表连接来说,包装器取出两个单表再自己作匹配,然后测试一下时间开销主要在应用服务器,就以为给数据库解了压。其实呢?你把连接用SQL实现,并不会给数据库更多开销。特别是当结果有聚合运算时,SQL出来的是分组后的计算结果,如果你试图用包装器再作分组运算,那么数据库不得不你提供大量的原始数据。
8. 必要时可以把生成的SQL打印到日志文件。
   你这开关是什么级别的?可以动态控制吗?如果我只需要看一个SQL, 会不会其他的也打印出来?
   用PLSQL编程,SQL是直接可见的,如果产生了错误数据比较容易找到源头。
9. 包装器会自动CACHE游标
   这在PLSQL中不足为奇。
   我想请教一下你们的三层结构是怎么样的?一个售票终端是否必需保持对一个应用服务器进程的连接?能否像互联网应用那样,配置若干个数据库连接来被无数的客户端共享?
10.一时想不出来,你自己凑吧。

你是来个全盘否定,连个二分法也不用。
我不想反驳你,但也不能被你说服。
不管怎么说,我们的程序是离不开DAU的。
它所创造的劳动生产率是你无法比拟的。就像一个雕塑师傅无法与铸造厂比生产率一样。师傅可以有一万条理由说铸造的工件不如艺术品。

还是忍不住想说一声。

包装器会利用数据字典自动生成模板。
   这就导致了大量的SELECT *, 也不管数据是否是必需的。这在真正的高端应用中就会体现出弱势来了。

你何时见我用select *了?我是坚决反对如此用法。只有你的例子是。你那个insert,不写列名,等同于select *。
仔细看看前边我的日志,列名都生成了,它很聪明,知道哪些列需要to_char(name,"YYYY-MM-DD"),哪些列需要to_char(name,"YYYY-MM-DD HH24:MI:SS"),
如果这个弄错了,数据就没法用了。如果没有模板系统,各个程序如果不一致,乱套了。DAU系统辅助了程序的可管理性。


特别是当结果有聚合运算时,SQL出来的是分组后的计算结果,如果你试图用包装器再作分组运算,那么数据库不得不你提供大量的原始数据。

可以手工建立分组模板。非常简单的,可以直接调用sdbc或sqlora,这两个东西是需要自己写语句的,我们的程序有这样的调用,我早说过,不是100%的。
大多数数据处理采用DAU就保证了开发效率、程序的可靠性,数据的规范性。

框架系统用到这个份上,存储过程不能支持模板,在我看来是最重大的缺陷。模板是一次定义多次使用的,实在是一个合算的买卖。
这两天弄了几个服务程序,模板,不仅用于数据库,几乎用于一切数据格式转换,DAU现在成了数据格式转换总线了,它可以把结构转换为任何格式。其中SQL语句和结果集,对它来说只不过是一种数据格式。现在名副其实的是:统一数据格式化处理系统。


关于效率,如果业务逻辑复杂,C程序效率更高,我不相信PL/SQL处理复杂数据能比C快。除了ASM,谁也没可能比C快。
我还是这个观点,数据库管理好数据,保证完整、正确、快速存取。其他事让别人做。

[ 本帖最后由 yulihua49 于 2009-2-24 11:46 编辑 ]

使用道具 举报

回复
论坛徽章:
7
2010数据库技术大会纪念徽章
日期:2010-05-13 09:34:22
239#
发表于 2009-2-24 10:50 | 只看该作者
如果你们两个是同事,我猜十有八九会打起来,哈哈

使用道具 举报

回复
论坛徽章:
281
2015年新春福章
日期:2015-03-06 11:57:312012新春纪念徽章
日期:2012-02-13 15:12:252012新春纪念徽章
日期:2012-01-04 11:51:22蛋疼蛋
日期:2011-12-29 07:37:22迷宫蛋
日期:2011-12-26 14:19:41茶鸡蛋
日期:2011-11-17 09:20:52茶鸡蛋
日期:2011-11-10 22:42:38ITPUB十周年纪念徽章
日期:2011-11-01 16:21:15茶鸡蛋
日期:2011-10-24 09:48:48ITPUB十周年纪念徽章
日期:2011-09-27 16:30:47
240#
发表于 2009-2-24 11:19 | 只看该作者
头脑风暴啊~~~

支持~~

思想的火花都是无数大脑的碰撞才产生的嘛~~

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表