楼主: 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
181#
 楼主| 发表于 2009-1-19 11:00 | 只看该作者
原帖由 yulihua49 于 2009-1-19 10:54 发表
多表采用:
DAU_getm(int n,DAU *DP,stmt);
n: DAU的个数,就是表的个数。
DP,DAU数组,每个表一个DAU。其中表名可以设别名。生成的每个列名都冠以 表别名. ,目前多表不支持bind。

DAU_nextm(int n,DAU *DP);
把结果集分别提取到各表的记录中。
DAU_freem(int n,DAU *DP);
释放所有DAU。


1.我们的事务极少使用复杂SQL,一般都是单表访问,由C程序组合逻辑,一般都是大量修改特定记录的,而且极少批量修改,多是单条修改。
2.复杂SQL语句通常执行时间很长,不在乎bind时间了。
3.多表bind太费事了,懒得做。
4.实在不行,脱了衣服赤膊上阵,自己干,也不妨调用存储过程。前边我有个例子调用存储过程的,只不过要小心 列-结构 的映射。
我们的整个设计是遵循20/80法则的,我只花20%的力气解决80%的问题。我说过,这个东西不是引擎,也不是驱动,就是件衣裳。80%-90%你穿着衣裳干活,省你不少事。个别情况你赤膊上阵,也不犯法。

[ 本帖最后由 yulihua49 于 2009-1-19 11:35 编辑 ]

使用道具 举报

回复
论坛徽章:
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
182#
 楼主| 发表于 2009-1-19 11:15 | 只看该作者

回复 #184 newkid 的帖子

"最近没闲着,程序已经包装到DAU里了,程序员可以透明的使用bind了。只是,如果数据有问题,看不出来,给调试造成一定麻烦。"
你可以设计一个较大的字符串,每绑定一个就往里面拼一截,最后看起来就像这样: 1:ABC|2EF|.....
执行SQL后如果有异常就把它写入日志。执行结束把它清空。

是个办法,速度会低一些,就更比不过ldr了。

我那个load,也不仅用于测试,其他一点用没有。就应用来说,每个记录不会像测试数据那样整齐划一,必须每个记录具体分析。这就不是SQLldr能做到了。

你前边也测了,加载发生重码,ldr很慢的,然后你再morge,时间之和?好几十秒了吧?
我在重码后立即update,很快的,7552个记录只需5.4秒,在这种情况下,我们的应用程序竟然比系统程序快了若干倍。
这个现象还没能得到满意的解释。
即为什么:
insert - DUPKEY - update 比
insert - DUPKEY - LOSS快很多倍。
我尝试用commit,rollback来控制,没有用。

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

使用道具 举报

回复
论坛徽章:
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
183#
发表于 2009-1-19 23:45 | 只看该作者
"DAU_nextm(int n,DAU *DP);
把结果集分别提取到各表的记录中。"

“连接”要的就是连接的效果,关系可能是一对多,多对多等等,你把好不容易连接好的结果集又给拆散了,前功尽弃。


"1.我们的事务极少使用复杂SQL,一般都是单表访问,……"
所以说,你这个方法局限性很大。复杂的查询根本应付不了。数据库访问的精髓在于高效的连接。


"2.复杂SQL语句通常执行时间很长,不在乎bind时间了。"
谁说的?复杂SQL语句并不意味着执行时间长!完全有可能解析时间大大超过执行时间。解析就是为了找出一个优化计划,使得执行代价尽可能小。所以解析完的“成果”就要尽可能再利用。


"就应用来说,每个记录不会像测试数据那样整齐划一,必须每个记录具体分析。这就不是SQLldr能做到了。"
你又张冠李戴了,SQLLDR是一个工具,用于特殊的目的(可以说就是用于加载你说的“整齐划一”的大批量数据),其他的任务自有其他办法,谁说一定用SQLLDR?
还是那句话:你要是有什么需求觉得用你的包装器很有优势的,请具体提出来。


“你前边也测了,加载发生重码,ldr很慢的,然后你再morge,时间之和?好几十秒了吧?”
你看贴不仔细。我#148用你的例子数据,全部代码都在,你自己去测试。我用三年前的旧机器,MERGE所有90万行数据也才用0.5秒。


"即为什么:
insert - DUPKEY - update 比
insert - DUPKEY - LOSS快很多倍。"

第一个里面都是什么动作?按我理解:

第一个:
INSERT;
IF DUP_VAL_ON_INDEX异常 THEN UPDATE;

第二个:
INSERT;
IF DUP_VAL_ON_INDEX异常 THEN 什么也不做;

因此第二个应该更快。

不管怎么说,用MERGE最快。

使用道具 举报

回复
论坛徽章:
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
184#
 楼主| 发表于 2009-1-20 09:15 | 只看该作者
原帖由 newkid 于 2009-1-19 23:45 发表
"DAU_nextm(int n,DAU *DP);
把结果集分别提取到各表的记录中。"

“连接”要的就是连接的效果,关系可能是一对多,多对多等等,你把好不容易连接好的结果集又给拆散了,前功尽弃。


"1.我们的事务极少使用复杂SQL,一般都是单表访问,……"
所以说,你这个方法局限性很大。复杂的查询根本应付不了。数据库访问的精髓在于高效的连接。


"2.复杂SQL语句通常执行时间很长,不在乎bind时间了。"
谁说的?复杂SQL语句并不意味着执行时间长!完全有可能解析时间大大超过执行时间。解析就是为了找出一个优化计划,使得执行代价尽可能小。所以解析完的“成果”就要尽可能再利用。


"就应用来说,每个记录不会像测试数据那样整齐划一,必须每个记录具体分析。这就不是SQLldr能做到了。"
你又张冠李戴了,SQLLDR是一个工具,用于特殊的目的(可以说就是用于加载你说的“整齐划一”的大批量数据),其他的任务自有其他办法,谁说一定用SQLLDR?
还是那句话:你要是有什么需求觉得用你的包装器很有优势的,请具体提出来。


“你前边也测了,加载发生重码,ldr很慢的,然后你再morge,时间之和?好几十秒了吧?”
你看贴不仔细。我#148用你的例子数据,全部代码都在,你自己去测试。我用三年前的旧机器,MERGE所有90万行数据也才用0.5秒。


"即为什么:
insert - DUPKEY - update 比
insert - DUPKEY - LOSS快很多倍。"

第一个里面都是什么动作?按我理解:

第一个:
INSERT;
IF DUP_VAL_ON_INDEX异常 THEN UPDATE;

第二个:
INSERT;
IF DUP_VAL_ON_INDEX异常 THEN 什么也不做;

因此第二个应该更快。

不管怎么说,用MERGE最快。

是的。
但是,不能不管怎么说,你在ldr阶段已经好几十秒了,game over。

因此第二个应该更快。为什么很慢很慢?无法解释,需要ORACLE的开发者来分析一下。

使用道具 举报

回复
论坛徽章:
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
185#
 楼主| 发表于 2009-1-20 09:25 | 只看该作者
原帖由 newkid 于 2009-1-19 23:45 发表
"DAU_nextm(int n,DAU *DP);
把结果集分别提取到各表的记录中。"

“连接”要的就是连接的效果,关系可能是一对多,多对多等等,你把好不容易连接好的结果集又给拆散了,前功尽弃。


"1.我们的事务极少使用复杂SQL,一般都是单表访问,……"
所以说,你这个方法局限性很大。复杂的查询根本应付不了。数据库访问的精髓在于高效的连接。


"2.复杂SQL语句通常执行时间很长,不在乎bind时间了。"
谁说的?复杂SQL语句并不意味着执行时间长!完全有可能解析时间大大超过执行时间。解析就是为了找出一个优化计划,使得执行代价尽可能小。所以解析完的“成果”就要尽可能再利用。


"就应用来说,每个记录不会像测试数据那样整齐划一,必须每个记录具体分析。这就不是SQLldr能做到了。"
你又张冠李戴了,SQLLDR是一个工具,用于特殊的目的(可以说就是用于加载你说的“整齐划一”的大批量数据),其他的任务自有其他办法,谁说一定用SQLLDR?
还是那句话:你要是有什么需求觉得用你的包装器很有优势的,请具体提出来。应用中的传输加、卸载器都是自己写,没有用ldr。



“连接”要的就是连接的效果,关系可能是一对多,多对多等等,你把好不容易连接好的结果集又给拆散了,前功尽弃。

no,有了结果就是成果,程序本来就是面向结构的。如果没有包装,就拆成一个一个的变量了,按你说法,岂不白干?存储过程怎么样?不是拆成一个一个的?

2.复杂SQL语句通常执行时间很长,不在乎bind时间了。"
谁说的?复杂SQL语句并不意味着执行时间长!完全有可能解析时间大大超过执行时间。解析就是为了找出一个优化计划,使得执行代价尽可能小。所以解析完的“成果”就要尽可能再利用。
"就应用来说,每个记录不会像测试数据那样整齐划一,必须每个记录具体分析。这就不是SQLldr能做到了。"
你又张冠李戴了,SQLLDR是一个工具,用于特殊的目的(可以说就是用于加载你说的“整齐划一”的大批量数据),其他的任务自有其他办法,谁说一定用SQLLDR?
还是那句话:你要是有什么需求觉得用你的包装器很有优势的,请具体提出来。

所以我说必要时允许使用存储过程啊。
不过现在我们的应用还没有用到存储过程,我极力向他们推荐,新系统是支持存储过程的。
因为我们处理的是高密度细碎事务,每个事务都很小,但数量极大,用包装器性能很高,程序易写好懂易维护。

[ 本帖最后由 yulihua49 于 2009-1-20 16:43 编辑 ]

使用道具 举报

回复
论坛徽章:
212
现任管理团队成员
日期:2012-01-16 14:02:09马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14ITPUB 11周年纪念徽章
日期:2012-10-09 18:06:202012欧洲杯之星
日期:2012-07-02 11:27:02奥运会纪念徽章:射击
日期:2012-06-27 15:36:35NBA季后赛纪念徽章
日期:2012-06-25 12:19:11NBA常规赛纪念章
日期:2012-04-27 16:07:05
186#
发表于 2009-1-20 11:22 | 只看该作者
关注

使用道具 举报

回复
论坛徽章:
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
187#
发表于 2009-1-21 00:10 | 只看该作者
"但是,不能不管怎么说,你在ldr阶段已经好几十秒了,game over。"
你这是在说我#148的MERGE吗?我那个例子根本不用加载,用外部表,加载时间是零!
要是不用外部表,先加载你的数据到临时表(注意,我是用STAGING TABLE, 因此不出错的),那么加载大约花2~3秒,再0.5秒的MERGE.

"因此第二个应该更快。为什么很慢很慢?无法解释,需要ORACLE的开发者来分析一下。"
你的第一种确实发生了异常吗?所有代码和第二种一样,并且还多了UPDATE动作?我有点不相信。把关键代码贴出来,我想看你异常的处理。

"no,有了结果就是成果,程序本来就是面向结构的。如果没有包装,就拆成一个一个的变量了,按你说法,岂不白干?存储过程怎么样?不是拆成一个一个的?"
存储过程里可不仅仅是对单表的操作(我想你指的是数据写入),还有很多查询。
给你个简单例子吧:
员工表,部门表。员工表里面只有部门ID, 没有部门名称。现在我查询一批员工信息,连同部门的名称。这个就是JOIN的典型应用。数据集是一个游标,结合了两张表的信息。
你的做法是怎么样呢?用你的两个DAU连接后,信息仍然被拆开,员工里面仍然只有部门ID,是不是?

使用道具 举报

回复
论坛徽章:
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
188#
 楼主| 发表于 2009-1-22 09:14 | 只看该作者
原帖由 newkid 于 2009-1-21 00:10 发表
员工表,部门表。员工表里面只有部门ID, 没有部门名称。现在我查询一批员工信息,连同部门的名称。这个就是JOIN的典型应用。数据集是一个游标,结合了两张表的信息。
你的做法是怎么样呢?用你的两个DAU连接后,信息仍然被拆开,员工里面仍然只有部门ID,是不是?

//#include <DAU_utility.h>
#include <kpapp.h>
JSON_OBJECT get_user(GDA *ctx,char *msg)
{
int ret;
DAU u_DAU[2];
JSON_OBJECT result,json;

        result=json_object_new_array();
        ret=DAU_init(&u_DAU[0],ctx->SQL_Connect,"user a",0,0);
        ret=DAU_init(&u_DAU[1],ctx->SQL_Connect,"unit b",0,0);
        sprintf(msg,"WHERE a.unit=b.unit_id");
        ret=DAU_getm(2,u_DAU,msg,0);
        while(!DAU_nextm(2,u_DAU)) {
                json=json_object_new_object();
                DAU_toJSON(&u_DAU[0],json,0);//user全部打包到json
                DAU_toJSON(&u_DAU[1],json,"unit_name");//组合unit_name到json
                json_object_array_add(result,json);//在JSON数组中加入一条记录
        }
        DAU_freem(2,u_DAU);
        return result;//JSON数组提交客户端,由其自行处理
}

[ 本帖最后由 yulihua49 于 2009-1-22 10:10 编辑 ]

使用道具 举报

回复
论坛徽章:
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
189#
 楼主| 发表于 2009-1-22 09:38 | 只看该作者
原帖由 newkid 于 2009-1-21 00:10 发表
"因此第二个应该更快。为什么很慢很慢?无法解释,需要ORACLE的开发者来分析一下。"
你的第一种确实发生了异常吗?所有代码和第二种一样,并且还多了UPDATE动作?我有点不相信。把关键代码贴出来,我想看你异常的处理。

源代码及内部处理细节在前边全文提供了,14页133楼。敬请分析。
ret=insrec(&_DAU,buf);
                if(ret) {
                        if(SQL_Connect->Errno == DUPKEY) {
                                if(!Pflg) {//如果没有-P选项,这很快
                                        ret=updaterec(&_DAU,buf);
                                        if(ret==0) upd+=1;
                                        else loss++;
                                }
                                else loss++;
                        } else {//这很慢,不必怀疑下面几句,其开销可以忽略不计。
                                DAU_pack(&_DAU,buf);
                                fprintf(ofd,"%s\n",buf);
                                ShowLog(1,"loadfile:%s",buf);
                                loss++;
                        }
                        rows--;
                        continue;
                }

[ 本帖最后由 yulihua49 于 2009-1-22 09:46 编辑 ]

使用道具 举报

回复
论坛徽章:
1
ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:44
190#
发表于 2009-1-22 09:42 | 只看该作者
呵呵,我会C语言!但是早就忘光了

使用道具 举报

回复

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

本版积分规则 发表回复

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