楼主: yulihua49

[PRO*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
541#
发表于 2010-8-26 23:10 | 只看该作者
原帖由 yulihua49 于 2010-8-26 10:15 发表

我也是个通用程序,没必要用它那个控制文件,有别的办法。
我没说你忽悠我,是我没注意。还有什么杀手锏?你还可以说,我还可以做。

最新结果,我把alter session commit_write = NOWAIT去掉了,结果:
sqlldr:0.978秒,净时间0.96秒
我是0.834秒,净时间0.710秒

还有一个不重要的问题,内存消耗。为了绑定这1000个记录它动用了14M内存,我不到1M。如果在多线程服务器里这就很有感觉了。

我如果多次绑定会比他慢。
你可以看49页490楼的那个程序,不包装,多次绑定,专用的,要比DAU慢50%以上。

但现在可以说,我的包装器效率不低于最精湛的oracle程序sqlldr。不需要怀疑包装器的效率了。
我可以设置alter session commit_write = NOWAIT而大幅度提速,他行吗?

比赛解析xls,就不必了,会把帖子弄爆的。那不过是另外一种读外部文件加入数据库的小技俩,并无通用性和普遍意义。
我不是说你不能做,而是不方便,即使做成,也是给数据库引擎造成极大压力,你干活时,卖不成票了。
所以,这种活还是不要存储过程干好。


去看看SQLLDR的文档,你会感叹于其强大的加载功能;不是说你要去用它的控制文件,意思是你的程序专注于其中的某一块,假如你也做到了类似的功能则性能上肯定要有所妥协。
你的SQLLDR控制文件和命令行参数怎么写的?试过SQLLDR直接路径加载和并行加载了吗?
COMMIT WRITE NOWAIT 也不是灵丹妙药,它也是有风险的,为了换取0.几秒的速度不值得。
你的包装器弊端不在于效率,在于助长了不学习SQL的思想,使用它的程序员满脑子都只有单表操作、嵌套循环的思路,倾向于写一大段代码来达到一小段SQL的功能。
你这个数据加载的例子只是一个特定情况下的应用。在此特定情况下(大批量数据重复使用一个简单SQL----仅仅单表的INSERT和UPDATE)你也许能达到或超过SQLLDR, 但你无法推断出此包装器在开发事务型系统(比如你的售票系统)也优于存储过程的方法。

我从来不赞成用存储过程解析XLS. 我上次就说过先转成文本(COPY & PASTE, 或者用VBA写一个简单的宏)。其他剩下的事(查站码,计算运行图,插入表)交给存储过程。数据库之外随便你用什么方法折腾,只要数据进了库(或者能被访问到,比如外部表),那就是SQL的SHOW TIME, 其他方法只好靠边站。我的杀手锏就是SQL。

使用道具 举报

回复
论坛徽章:
1088
金色在线徽章
日期:2007-04-25 04:02:08金色在线徽章
日期:2007-06-29 04:02:43金色在线徽章
日期:2007-03-11 04:02:02在线时间
日期:2007-04-11 04:01:02在线时间
日期:2007-04-12 04:01:02在线时间
日期:2007-03-07 04:01:022008版在线时间
日期:2010-05-01 00:01:152008版在线时间
日期:2011-05-01 00:01:342008版在线时间
日期:2008-06-03 11:59:43ITPUB年度最佳技术原创精华奖
日期:2013-03-22 13:18:30
542#
发表于 2010-8-26 23:38 | 只看该作者
LZ的研究精神还是值得学习的,为他们老板节省了资源,找个简单程序员就可以干活了,LZ可以当领导

newkid的你的包装器弊端不在于效率,在于助长了不学习SQL的思想,使用它的程序员满脑子都只有单表操作、嵌套循环的思路,倾向于写一大段代码来达到一小段SQL的功能。

我很赞同。

呵呵,虽然这种包装的东西现在很多,但是还是原装的好啊

使用道具 举报

回复
论坛徽章:
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
543#
发表于 2010-8-26 23:55 | 只看该作者
把TOM关于COMMIT WRITE NOWAIT的说法转贴:

This might suggest that you’d want to use this COMMIT WRITE NOWAIT all of the time—after all isn’t
performance the most important thing in the world? No, it is not. Most of the time, you need the
durability achieved by default with COMMIT. When you COMMIT and report back to an end user “we have
committed,” you need to be sure that the change is permanent. It will be recorded in the database even
if the database/hardware failed right after the COMMIT. If you report to an end user that “Order 12352 has
been placed,” you need to make sure that Order 12352 was truly placed and persistent. So, for most every
application, the default COMMIT WRITE WAIT is the only correct option (note that you only need say
COMMIT—the default setting is WRITE WAIT).
When would you want to use this new capability to commit without waiting then? Three scenarios
come to mind:
• A custom data load program. It must be custom, since it will have additional logic
to deal with the fact that a commit might not persist a system failure.
• An application that processes a live data feed of some sort, say a stock quote feed
from the stock markets that inserts massive amounts of time-sensitive
information into the database. If the database goes offline, the data stream keeps
on going and the data generated during the system failure will never be processed
(Nasdaq does not shut down because your database crashed, after all!). That this
data is not processed is OK, because the stock data is so time-sensitive, after a few
seconds it would be overwritten by new data anyway.
• An application that implements its own “queuing” mechanism, for example one
that has data in a table with a PROCESSED_FLAG column. As new data arrives, it is
inserted with a value of PROCESSED_FLAG='N' (unprocessed). Another routine is
tasked with reading the PROCESSED_FLAG='N' records, performing some small, fast
transaction and updating the PROCESSED_FLAG='N' to 'Y'. If it commits but that
commit is later undone (by a system failure), it is OK because the application that
processes these records will just process the record again—it is “restartable.”

使用道具 举报

回复
论坛徽章:
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
544#
 楼主| 发表于 2010-8-27 14:22 | 只看该作者
原帖由 newkid 于 2010-8-26 23:10 发表


去看看SQLLDR的文档,你会感叹于其强大的加载功能;不是说你要去用它的控制文件,意思是你的程序专注于其中的某一块,假如你也做到了类似的功能则性能上肯定要有所妥协。
你的SQLLDR控制文件和命令行参数怎么写的?试过SQLLDR直接路径加载和并行加载了吗?
COMMIT WRITE NOWAIT 也不是灵丹妙药,它也是有风险的,为了换取0.几秒的速度不值得。
你的包装器弊端不在于效率,在于助长了不学习SQL的思想,使用它的程序员满脑子都只有单表操作、嵌套循环的思路,倾向于写一大段代码来达到一小段SQL的功能。
你这个数据加载的例子只是一个特定情况下的应用。在此特定情况下(大批量数据重复使用一个简单SQL----仅仅单表的INSERT和UPDATE)你也许能达到或超过SQLLDR, 但你无法推断出此包装器在开发事务型系统(比如你的售票系统)也优于存储过程的方法。

我从来不赞成用存储过程解析XLS. 我上次就说过先转成文本(COPY & PASTE, 或者用VBA写一个简单的宏)。其他剩下的事(查站码,计算运行图,插入表)交给存储过程。数据库之外随便你用什么方法折腾,只要数据进了库(或者能被访问到,比如外部表),那就是SQL的SHOW TIME, 其他方法只好靠边站。我的杀手锏就是SQL。


DAU并非只能做单表,前边的例子有许多就是多表的。你如果精通SQL同样可以写出丰富多彩的模板,进行高效率处理。只不过他“容忍”了无知,甚至对SQL几乎无知的程序员也可以写出不错的程序。一个开发团队里,高手毕竟是少数,大批的程序员是近乎无知的。这是开发成本决定的。所以你说的问题存在,但他不是DAU的错。还是20/80法则,80%的代码可以轻松写成,然后你用80%的精力专攻那20%的关键代码。总成本最低,开发周期最短。

commit的问题我明白。所以在DAU里它是个配置项,你希望提高速度就要承担风险。在你愿意承担风险的情况下,我可以给你提高速度。愿意乘飞机,就别怕掉下来。
我也可以告你,飞机很安全,掉下来的概率很低。

在存储过程里,commit是NOWAIT的,你没发现commit的时间非常短?

这里,都是高手,能在SQL的海洋里自由驰骋。船?谁需要那玩意儿?碍手碍脚。大陆上的,怕水,给他们船,他们就可以过海。有了好船,可以更快。
你可以说,让他们学游泳。谈何容易?会几下子的,也成不了游泳健将。我造船,他们也可以学开船,学开船不耽误学游泳,游泳好也不耽误学开船。
对普罗大众而言,是学了游泳再过河好呢?还是坐船?

船,刚发明出来(不只一种,不同的地方有不同的船),还显笨拙,也不见得跑得快,但他最终能跑得更快,也能载更多的人和货。现在要想让游泳者接受它,还需要一个过程。我希望在这些游泳高手中能出一个船长,可以带普罗大众出海,还可以告诉我,船,怎样更好。

这里,又有一个想搞包装的,还不成样子。
http://bbs.chinaunix.net/thread-1774336-1-1.html
他的问题,DAU_update()不就完事了?

[ 本帖最后由 yulihua49 于 2010-8-27 15:00 编辑 ]

使用道具 举报

回复
论坛徽章:
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
545#
发表于 2010-8-27 21:44 | 只看该作者
我知道你的包装器可以写任何SQL, 问题是在这种环境下写SQL,开发效率、可读性、可维护性比存储过程差了很多,对于一个熟悉SQL的人来说包装器反而成了累赘。
我不同意你关于游泳、坐船的比喻,按照同时精通C语言、SQL和PLSQL的TOM大师的说法,掌握C语言难度更大。你的比喻倒调过来还差不多。
PLSQL的COMMIT缺省是NOWAIT的,但是在返回给客户端时会做一次同步。况且,在存储过程里提交是不推荐的做法,事务控制应该放到客户端完成。

使用道具 举报

回复
论坛徽章:
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
546#
 楼主| 发表于 2010-10-22 16:05 | 只看该作者
原帖由 yulihua49 于 2010-10-22 15:47 发表

今天,到现在为止,DAU的DB2包装基本完成了。
有些与ORACLE不同,1.没找到RETURNING子句的写法,2.存储过程接口暂缺。3.数组插入操作还没做。db2的数组读取是比较方便的,已经实现了。

前边说的ORACLE的怪异现象不存在,插入时发生重码就跳过,速度比成功插入要快。
插入时发生重码就修改,与纯插入速度差不多,这点比ORACLE好。

纯粹插入,真正的操作是比ORACLE快的,插7552个记录,0.8秒,ORACLE是1.2秒。但最后的CLOSE DATABASE,0.5秒,拉了后腿,整体速度与ORACLE差不多。
单条插入,每秒9000啊,不简单。

软解析,在连接内有效,不像ORACLE全部有效。这样,使用中间件就很有必要,中间件打开一些数据库连接,大量用户共享这些连接,这些连接里的语句都可以软解析。

现在看来,不写SQL语句真好。在ORACLE下生成ORACLE语句,在DB2下生成DB2语句,应用程序无需修改。

如你写了一个语句:

sprintf(stmt,"where begdate<=:begdate and enddate >=:begdate")
在ORACLE下,生成:
。。。。。。。。where begdate<=to_date(:12,'YYYY-MM-DD') and enddate>=to_date(:13,'YYYY-MM-DD')
在DB2下生成:
。。。。。。。。where begdate<=? and enddate>=?

应用程序一点都不改的。真好。

分析一个表结构,用以生成模板,ORACLE需要6ms,没有软解析,因为用到多表查询(一次双表查询,一次单表查询)。
DB2需要20ms(三个单表查询),但分析第二次就只需要1.2ms了,在本连接内实现了软解析。

还是前边那个tjrb表,生成这样的语句:

INSERT INTO ZHOUGX.tjrb (TJDATE,UNIT,TABNAME,FLG,DAT1,DAT2,DAT3,DAT4,DAT5,DAT6,DAT7,DAT8,DAT9,DAT10,DAT11,DAT12,DAT13,DAT14,
DAT15,DAT16,DAT17,DAT18,DAT19,DAT20,DAT21,DAT22,DAT23,DAT24,DAT25,DAT26,DAT27,DAT28,DAT29,DAT30,DAT31,DAT32,DAT33,DAT34,
DAT35,DAT36,DAT37,DAT38,DAT39,DAT40,DAT41,DAT42,DAT43,DAT44,DAT45,DAT46,DAT47,DAT48,DAT49,DAT50) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
而update语句成了这个样子:
UPDATE ZHOUGX.tjrb SET TJDATE=? ,UNIT=? ,TABNAME=? ,FLG=? ,DAT1=? ,DAT2=? ,DAT3=? ,DAT4=? ,DAT5=? ,DAT6=? ,DAT7=? ,DAT8=? ,
DAT9=? ,DAT10=? ,DAT11=? ,DAT12=? ,DAT13=? ,DAT14=? ,DAT15=? ,DAT16=? ,DAT17=? ,DAT18=? ,DAT19=? ,DAT20=? ,DAT21=? ,DAT22=? ,
DAT23=? ,DAT24=? ,DAT25=? ,DAT26=? ,DAT27=? ,DAT28=? ,DAT29=? ,DAT30=? ,DAT31=? ,DAT32=? ,DAT33=? ,DAT34=? ,DAT35=? ,DAT36=? ,
DAT37=? ,DAT38=? ,DAT39=? ,DAT40=? ,DAT41=? ,DAT42=? ,DAT43=? ,DAT44=? ,DAT45=? ,DAT46=? ,DAT47=? ,DAT48=? ,DAT49=? ,DAT50=?  
WHERE TJDATE=?  AND UNIT=?  AND TABNAME=?  AND FLG=? ,

[ 本帖最后由 yulihua49 于 2010-10-22 17:07 编辑 ]

使用道具 举报

回复
论坛徽章:
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
547#
发表于 2010-10-22 21:45 | 只看该作者
“现在看来,不写SQL语句真好。在ORACLE下生成ORACLE语句,在DB2下生成DB2语句,应用程序无需修改。”
如果你的应用全是最最基本的DML还差不多,高级一点的如分析函数就很不同了。
锁呢?我听说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
548#
 楼主| 发表于 2010-10-24 12:20 | 只看该作者
原帖由 newkid 于 2010-10-22 21:45 发表
“现在看来,不写SQL语句真好。在ORACLE下生成ORACLE语句,在DB2下生成DB2语句,应用程序无需修改。”
如果你的应用全是最最基本的DML还差不多,高级一点的如分析函数就很不同了。
锁呢?我听说DB2的锁是很不同的,而且它还没有一致读。

说得很对,世上没有绝对的东西。用20/80法则来折中工程问题就好了。
它的锁的说道很多,我也没完全懂。不过,基本的行锁还是具备的,逻辑比较严格,如果没有写for updata,是不准改当前记录的。

另外,4个隔离级都支持。

不是没有一致读,而是一致读时要锁定结果集,非锁定的,到9.7才支持。

没找到RETURNING字句,令人沮丧。

没有ROWID,时有不便。但可以 update ... where current of cursor_name;有所补偿。
ORACLE也可以,但在OCI里找不到cursor_name.

不写语句太好了,比如前边那54个?,写也不难,多写少写一个,你就自己看着办了。——王婆卖瓜。

[ 本帖最后由 yulihua49 于 2010-10-24 12:31 编辑 ]

使用道具 举报

回复
论坛徽章:
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
549#
 楼主| 发表于 2010-10-25 17:43 | 只看该作者

回复 #557 yulihua49 的帖子

找到RETURNING子句了,在DB2 V9.7里支持:
http://publib.boulder.ibm.com/in ... c/doc/c0053868.html
在update和delete语句,不允许returning多记录的结果集。而ORACLE是可以的,用原语句的cursor,FETCH即可。

PL/SQL与ORACLE何其相似。


V9.7的CLI不能连接V9.5的服务器,版本间的兼容性差。

[ 本帖最后由 yulihua49 于 2010-10-25 17:50 编辑 ]

使用道具 举报

回复
论坛徽章:
0
550#
发表于 2012-7-17 17:29 | 只看该作者

来晚了 错过了 哈哈。 不过真的很好。

使用道具 举报

回复

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

本版积分规则 发表回复

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