楼主: yulihua49

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

[复制链接]
论坛徽章:
0
101#
发表于 2008-12-11 17:11 | 只看该作者
不错,oracle的顺序写redo和读一致性的机制决定了它是一个适应了高并发的数据库,这点特性DB2也不如,不发挥其特长有点可惜,毕竟几十万买了的软件,不好好用好太浪费了。

使用道具 举报

回复
论坛徽章:
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
102#
 楼主| 发表于 2008-12-11 17:37 | 只看该作者

做了一个调用存储过程的DAO

#include <DAO.h>

static T_PkgType seat_proc_type[]={
        {CH_INT,sizeof(int),"cursor",0,-1},
        {CH_INT,sizeof(int),"num"},
        {-1,0,0,0}
};

typedef struct  {
        int cursor;
        int num;
} seat_proc_s;

DAU * get_seat_for_sale(DAU *DP,int quantity,char *userid,char *devidi,char *stmt);
{
DAU proc_DAU;
SEAT_s *seat;
int ret;
char *result;
seat_proc_s p_proc;
DAU *p_DAU;

        seat=DP->srm.rec;
        sprintf(stmt,"getseat_for_sell(:cursor,:num,%s,%s,%s,%d,%d,%d,%d,%s,%s)",
                ,seat->start_date, seat->train_no ,seat->beg_station,seat->end_statio ,seat->seat_type ,
                seat->purpose ,quantity ,userid ,devid);
        ret=ORA_Rpc(DP->SQL_Connect,stmt,&result);
        if(ret) {
                if(result) free(result);
                return NULL;
        }      
        net_dispack(&p_proc,result,seat_proc_type);
        free(result);
        p_DAU=(DAU *) malloc(sizeof(DAU));
        if(!p_DAU) {
                ___SQL_Close__(DP->SQL_Connect,p_proc.cursor);
                return NULL;
        }
        DAU_init(p_DAU,DP->SQL_Connect,0,DP->srm.rec,DP->srm.tp);//模板可是听天由命了,能对齐吗?
        p_DAU->cursor=p_proc.cursor;
        p_DAU->srm.result=stmt;
        return p_DAU; //回头自己释放吧。
}

后边DAU_next(p_DAU);
一个一个来吧。

我是没敢确定DP将来是否有用,不然直接收拾DP省得分配了。
num没用,DAU_next到底就行了。

[ 本帖最后由 yulihua49 于 2008-12-11 17:53 编辑 ]

使用道具 举报

回复
论坛徽章:
66
皇马
日期:2009-02-13 09:38:532011新春纪念徽章
日期:2011-02-18 11:43:342010广州亚运会纪念徽章:柔道
日期:2011-04-08 23:11:212010广州亚运会纪念徽章:排球
日期:2011-04-18 22:00:58鲜花蛋
日期:2011-05-30 21:23:49ITPUB十周年纪念徽章
日期:2011-11-01 16:24:04ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15迷宫蛋
日期:2012-12-18 23:39:42问答徽章
日期:2013-09-25 16:14:23优秀写手
日期:2015-02-12 06:00:13
103#
发表于 2008-12-11 19:08 | 只看该作者
自从看了TOM的书后  我还是觉得不要把数据库当黑盒使用的好

免得出现向TOM书前面举的那几个例子一样

使用道具 举报

回复
论坛徽章:
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
104#
发表于 2008-12-11 23:41 | 只看该作者
"这正是我前边提出的万能制表和统计分析软件。"
你这个只是界面工具吧?关键是数据怎么算出来的,还得靠SQL完成吧?说实在的,优秀的界面工具多的是,很多也有查询生成功能,但做出来的查询只能是很简单的,复杂的SQL还要手工完成。

"purpose不能作为主键。主键只能是上述表结构定义的。你不怕相同的席位因为不同的purpose而重复吗?"
谁说要把PURPOSE作为主键了?我前面只是想过把PURPOSE加入到复合索引里,这样可缩小找票范围。看了你的数据,我决定采用(START_DATE,BEG_STATION,TRAIN_NO), 跟PURPOSE没有关系了。

"在席位表里,另外的唯一ID绝不可用。"
说出个道理来?要是我来设计这张表,绝对要有一个票号作主键的,就是一个NUMBER在插入的时候生成SEQUENCE值,有什么困难的?这个号码打印出来,对很多处理都很有用。我前面问过你退票的问题你没有回答。


"最好用上面的SELECT,回来的结果集我好拆包。"
你还用+rule呢,这早就被ORACLE抛弃了。
按你的结构定义内存数组或临时表, 存储过程不用改:

DROP TYPE tp_seat_table2;

CREATE OR REPLACE FORCE TYPE tp_seat2 AS OBJECT (
      start_date            VARCHAR2(20)
     ,beg_station           VARCHAR2(4)
     ,train_no              VARCHAR2(12)
     ,run_train             VARCHAR2(6)
     ,on_date               VARCHAR2(20)
     ,carno                 NUMBER(2)
     ,seat_type             NUMBER(2)
     ,seat_no               NUMBER(3)
     ,end_station           NUMBER(3)
     ,shortest_station      NUMBER(3)
     ,purpose               NUMBER(9)
     ,gride                 varchar2(50)
     ,pro                   varchar2(5)
     ,flag                  NUMBER(1)
     ,used_dev              varchar2(16)
     ,used_uid              varchar2(16)
     ,used_time             varchar2(20)
     ,row_id                VARCHAR2(20)
     )
/

CREATE OR REPLACE TYPE tp_seat_table2 AS TABLE OF tp_seat2
/


"我这模板比hibernat快几个数量级,hibernate能用,我的为什么不能用?"
我不知道hibernat怎么做的,但我建议你去研究一下它对绑定变量的处理。

"没有模板,你上哪找struct里边的成员?"
我没有说不用模板,我的意思是"运行时"不要模板。这就是说把模板作为开发工具,生成源代码(里面无非就是一堆赋值语句)。
这会使得整个性能再上一个台阶。当然了,你现在的做法也有其好处,就是代码量少,如果性能已经达到你的要求也无妨。

"你那个 lv_rec 哪定义的?上来就可以 FOR 吗?"
FOR循环用的变量不用事先定义,直接使用。但超出循环就不可见了。
建议你学习一下PLSQL(比C语言容易得多), 你会发现它的很多好处,最大的好处就是和SQL的无缝接口,全部变量自动绑定。你可以看到在存储过程中使用SQL是多么自然的事,这和C语言是完全不同的。

使用道具 举报

回复
论坛徽章:
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
105#
发表于 2008-12-12 03:50 | 只看该作者
仔细看了一下你的UPDATE生成模块,不出所料的没有用上绑定变量。
最要命的是这个: WHERE ROWID = 'AAAM3iAAFAAAEpkAAw'

看看你以前自己说过的话:
“相同的日期、车次、始发站、到达站、席别、用途,就会产生一模一样的SQL语句!”

这下子你还认为会产生一模一样的SQL语句吗?每条记录的ROWID可都是不一样的!
我很想看看你这售票模块在大规模压力测试下的表现!

使用道具 举报

回复
论坛徽章:
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
106#
 楼主| 发表于 2008-12-12 09:52 | 只看该作者
原帖由 newkid 于 2008-12-12 03:50 发表
仔细看了一下你的UPDATE生成模块,不出所料的没有用上绑定变量。
最要命的是这个: WHERE ROWID = 'AAAM3iAAFAAAEpkAAw'

看看你以前自己说过的话:
“相同的日期、车次、始发站、到达站、席别、用途,就会产生一模一样的SQL语句!”

这下子你还认为会产生一模一样的SQL语句吗?每条记录的ROWID可都是不一样的!
我很想看看你这售票模块在大规模压力测试下的表现!

我永远不会使用绑定变量的,如果一定要使用绑定变量,可以拿到OCI句柄;SQL_Connect->dbh,通过sqlora8或OCI去使用,我不反对。
我这么做过,没发现效率改进,还费了我不少事。
还有,数据库可能在千里之外,通过安全代理转发器访问,代理器是不能绑定变量的,为了与之兼容,有数据库我也不绑。
ODBC因为绑定变量,网络效率极低,所以SDBC(安全数据库连接)取消变量绑定,采取值传输,效率大为提高。
越南铁路售票系统采取SDBC,在64K环路上,河内到西贡,全部终端的数据库处理十分顺畅,ODBC是根本无法使用的。
十几年来,与ODBC无数次碰撞,ODBC无不大败而归。

这是席位生成程序,对每天所有车次各种席位反复调用的语句,我指望这样能节约一些语句分析的开销,没达到目的,反而慢了一点点。
if(stop_station_sth == SQLO_STH_INIT) { //第一次
                    sprintf(stmt,"select %s from %s.stop_station where "
                        "train_no= :1  and item= :2 and "
                        "beg_date <= to_date(:3,'%s') and "
                        "end_date >= to_date(:4,'%s') and over>0 ",
                        mkfield(tmp,stop_station_type,0),
                        SQL_Connect->DBOWN,
                        YEAR_TO_DAY, YEAR_TO_DAY);
                    ret=sqlo_open2(&stop_station_sth,SQL_Connect->dbh,stmt,
                                4,argv);
ShowLog(5,"为无号查找停靠站表 stmt=%s,ret=%d",  stmt,ret); //日志里的语句,都是:占位符,根本不知道值是否合理,是否正确。
                    if(ret<0) {
                        ___SQL_GetError(SQL_Connect);
                        ShowLog(1,"WHFB stmt=%s,err=%d,%s",stmt,
                                SQL_Connect->Errno,
                                SQL_Connect->ErrMsg);
                    }
                } else { //以后每次,只更换argv里的4个值。
                    ret=sqlo_reopen(stop_station_sth,4,argv);
                    if(ret<0) {
                        ___SQL_GetError(SQL_Connect);
                        ShowLog(1,"WHFB reopen,err=%d,%s",
                                SQL_Connect->Errno,
                                SQL_Connect->ErrMsg);
                    }
                }

还有seat_sth,station_sth,全部过程都如此处理,结果没发现有任何好处。

这说明,我的工具仅仅是个包装器,如果你有特殊需求,完全可以脱掉包装直接使用内核。

[ 本帖最后由 yulihua49 于 2008-12-12 10:23 编辑 ]

使用道具 举报

回复
论坛徽章:
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
107#
 楼主| 发表于 2008-12-12 10:31 | 只看该作者
原帖由 srw3 于 2008-12-11 17:11 发表
不错,oracle的顺序写redo和读一致性的机制决定了它是一个适应了高并发的数据库,这点特性DB2也不如,不发挥其特长有点可惜,毕竟几十万买了的软件,不好好用好太浪费了。

我们是看中ORA的这些特性啊! 我们一直在用啊,我们的工具系统支持这些特性的。

使用道具 举报

回复
论坛徽章:
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
108#
 楼主| 发表于 2008-12-12 10:46 | 只看该作者
原帖由 newkid 于 2008-12-11 00:15 发表
"SQL语句的分析问题,充其量是计算问题,不是IO问题,高主频的CPU轻易化解,永远成不了瓶颈。"
前面你还说要缓解数据库的负担呢?绑定变量的问题确实是CPU问题,这个不是升级能解决的,基本上你有多少资源都会被吃掉。CPU成瓶颈,后面的IO只好跟着等待,这是绕不过的。


我们开发的软件,十几年了,一直用SDBC,一直是这么处理,所有项目,服务器都是特别轻松的,CPU率很低。
象地区级售票系统,当年约400客户端,地区级行包系统,约200,大型编组站现车管理120左右,接发车自动编解统计分析等等,就是一个ALPHA1200的低档小型机,过去用别的软件忙不过来,用SDBC轻松应对。忙时CPU 5%-10%。
另一个小点的站(也是大站),原来用sdbc很轻松,换部标软件,delphy+ODBC,根本干不动,CPU和IO都特别沉重,不得已升级机器后勉强能用,响应速度无法跟SDBC比的。
这些工具原来都是我们的秘密武器,领导要求保密的。现在单位解体了,我才公开。

使用道具 举报

回复
论坛徽章:
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
109#
 楼主| 发表于 2008-12-12 17:30 | 只看该作者
原帖由 newkid 于 2008-12-11 23:41 发表
"这正是我前边提出的万能制表和统计分析软件。"
你这个只是界面工具吧?关键是数据怎么算出来的,还得靠SQL完成吧?说实在的,优秀的界面工具多的是,很多也有查询生成功能,但做出来的查询只能是很简单的,复杂的SQL还要手工完成。

""purpose不能作为主键。主键只能是上述表结构定义的。你不怕相同的席位因为不同的purpose而重复吗?"
谁说要把PURPOSE作为主键了?我前面只是想过把PURPOSE加入到复合索引里,这样可缩小找票范围。看了你的数据,我决定采用(START_DATE,BEG_STATION,TRAIN_NO), 跟PURPOSE没有关系了。


那要另建索引囖,那可要综合考虑,索引我们是比较慎重的。

那个工具,数据提取器是内部程序,表格是界面。现在界面工具有的是,我倒不特别强调。反正有这个老古董,谁有兴趣就给谁。

这个程序当年承受力当时很大的吞吐量,掌管整个北京地区6站一中心售票,是当时全国最大的,用的200M主频4CPU的MIPS机器,完成的比较轻松。
当时是INFORMIX,我的程序,与你那个存储过程的功能类似。但是INFORMIX是在FETCH时处理锁的,prepare阶段就像你的第一步,无锁收集结果集,FETCH时跳锁。
免去了你第二步的SQL解析。

我不会用ROWID做持久化对象的,你放心。

你那个程序我想这样行不行:
第一步,无锁收集ROWID,第二步,带锁收集其他字段。第三步占用,第四步打包输出,开销似乎可以小一些。
因为第一步行很多,字段数少一些,第二步就只有很少的行了。

[ 本帖最后由 yulihua49 于 2008-12-12 17:45 编辑 ]

使用道具 举报

回复
论坛徽章:
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
110#
发表于 2008-12-13 00:10 | 只看该作者
"我永远不会使用绑定变量的,……"
虽然有点遗憾但也不意外,我像个传教士讲了这么多遍,都有点佩服自己了
你们不是和ORACLE公司交流过技术方案吗?他们对于绑定变量是什么看法?如果哪个技术专家对我的说法有异议,我倒很想见识一下。随便他选哪个论坛,我立马过去和他单挑!


"我这么做过,没发现效率改进,还费了我不少事。"
我看了你下面的语句,你们的测试数据是怎么样的,取值的组合一共有多少种?如果你只用几十组值作测试,虽然事务很多,但不绑定变量无所谓。
我强烈建议你用WHERE ROWID='AAAM3iAAFAAAEpkAAw'这样的语句,作一个大规模的压力测试。


"还有,数据库可能在千里之外,通过安全代理转发器访问,代理器是不能绑定变量的,……"
有没有这个SDBC的资料?是你们自己发明的吗?
一般来说,应用服务器和数据库是在很安全的内网,我们不会在它们之间再设置任何障碍。ORACLE也有很成熟的安全连接方案,我不相信绑定变量会用不了。


"ODBC因为绑定变量,网络效率极低,……"
你是如何确定这个原因的?作过对比测试吗?一个系统做的不好,原因多了去了。


"越南铁路售票系统采取SDBC,在64K环路上,河内到西贡,全部终端的数据库处理十分顺畅,ODBC是根本无法使用的。"
我怀疑你们的参数是这么设置的:cursor_sharing = force 或者 similar
这个开关是专门应付你们这种设计方法的,但有其副作用,最好不用。


"十几年来,与ODBC无数次碰撞,ODBC无不大败而归。"
我的存储过程写出来了,等着和你碰撞呢。


"我们开发的软件,十几年了,一直用SDBC,一直是这么处理,所有项目,服务器都是特别轻松的,CPU率很低。"
越来越怀疑cursor_sharing开关是打开的。
压力测试怎么做的?像我那样并发请求同样的票做了吗?


"这些工具原来都是我们的秘密武器,领导要求保密的。现在单位解体了,我才公开。"
不客气地说,您这属于敝帚自珍。这套做法放到真正密集型的OLTP, 如电信银行,那是会力不从心的。


"那要另建索引囖,那可要综合考虑,索引我们是比较慎重的。"
我倒不理解了:索引不就是为应用服务的吗?我这个索引可是参照了你的数据分布建立的,用你的数据,最多扫描664行。你们用什么索引?
我加入的这个索引就是在生成数据的时候有开销,但那是另一个批量处理,不会影响你平时的业务。


"当时是INFORMIX,我的程序,与你那个存储过程的功能类似。但是INFORMIX是在FETCH时处理锁的,prepare阶段就像你的第一步,无锁收集结果集,FETCH时跳锁。
免去了你第二步的SQL解析。"

INFORMIX的写会阻塞读,而且它的行锁是靠字典管理的,系统开销大,比起ORACLE那不知是差了十万八千里! 你的程序实际上是在“排队取票”,不是“抢票”。


"你那个程序我想这样行不行:
第一步,无锁收集ROWID,第二步,带锁收集其他字段。第三步占用,第四步打包输出,开销似乎可以小一些。
因为第一步行很多,字段数少一些,第二步就只有很少的行了。"
我的程序和你的四个步骤基本一致,就是第一第二相反了。但是第一步的查询条件/排序条件,光凭索引是搞不定的(我就建了几列你都有意见了!总不能把所有列都塞进去),所以说第一步读表是不可避免的。
因为修改很简单,我等会也会根据你的意见再做一个版本。

使用道具 举报

回复

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

本版积分规则 发表回复

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