楼主: 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
211#
 楼主| 发表于 2009-2-10 10:09 | 只看该作者
原帖由 newkid 于 2009-2-9 23:32 发表
按你的说法,是调用了一段代码(updaterec)比什么事也不做还更快。有两种方法可以调查:
1. 当你认为“比什么事也不做”时,实际上程序走了别的分支,这是我觉得最可能的猜测。只要作一次全面跟踪就可以搞清楚。
2. 把updaterec里面的代码替换成别的动作,甚至什么也不做直接返回,看看时间又如何?是不是因为原来的代码修改了全局变量影响到后面循环的执行?

你这个真正的卖票程序不公开我就没法和你PK了,等哪天你有公开的需求再来玩。

现在采取一个变通的办法。
完全的业务逻辑测试n遍(每遍后都把占用的席位释放)。取时间的典型值。
单独取消席位申请,再测试n遍,取典型时间值。
它们之差是否有代表性?
300个终端争夺:
有席位申请: 7.970秒
无席位申请: 6.521
差:1.449
我是4核处理机,从客户端-服务器-数据库都在一台机器上。
至于谁都时间多一点,少一点已经无关紧要,这个系统的性能效率已经完全令人满意,这就够了。
优良的负载均衡效果和近乎线性的负载-响应时间,使我们对未来有良好预期。

什么事也不做确实没有别的分支,就是按你的办法单独注释掉update语句的。
建议你做个试验。你前边不是有个SQLloader +append的测试,重码90秒吗?我这里带update才5秒啊,还不说明问题吗?问题肯定在ORACLE内部。

关于框架,大家所见略同,各村有各村的高招,从Hibernat到.net,包括PB,还有其他平台。
我需要LINUX平台,C语言,服务器端(无交互)的应用框架,到现在为止还没有找到类似的,而且没有发现与我有类似需求的。所有这些技术都是互相借鉴的,将来谁有类似需求,欢迎切磋。

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

使用道具 举报

回复
论坛徽章:
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
212#
发表于 2009-2-10 10:30 | 只看该作者
SQLloader的动作我不能控制,它遇到错误只能写日志,不能进行UPDATE.
我可以用PLSQL模拟你的操作,但是不具备可比性,因为你是接收到来自数据库抛出的异常,而我不得不在数据库内部捕获异常。等我明天有空了试一下。
你的业务我无从了解,但300个终端确实是小意思,我相信你的方法可以满足需求。但你别说可以胜过存储过程!

使用道具 举报

回复
论坛徽章:
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
213#
 楼主| 发表于 2009-2-10 10:50 | 只看该作者
原帖由 newkid 于 2009-2-10 10:30 发表
SQLloader的动作我不能控制,它遇到错误只能写日志,不能进行UPDATE.
我可以用PLSQL模拟你的操作,但是不具备可比性,因为你是接收到来自数据库抛出的异常,而我不得不在数据库内部捕获异常。等我明天有空了试一下。
你的业务我无从了解,但300个终端确实是小意思,我相信你的方法可以满足需求。但你别说可以胜过存储过程!

老弟(大概可以这样称呼)对存储过程始终不渝的忠实挚爱着实令我钦佩。
但系统的可维护性和易变更性是我们的不变需求。数据与程序独立,是几十年前提出的,至今仍是我的理想。这些是我们开发和使用框架的动力和手段。
框架的意义在于20/80法则,80%的需求是简单需求,框架给予完全的支持。20%的复杂需求,框架允许使用你自己的解决方案,从自定义模板到完全的SQL语句的书写,甚至于调用存储过程都是可以的。
当然,弊端是存在的,当一个简单方案存在时,人们就不动脑子了,就用简单方法去堆砌程序(我就是这样,至今对SQL一知半解),对于个人进步不利。但是对于工程来说,只能这样,用最简单的劳力制造复杂产品。
我制造生产线,劳动生产率是最重要的指标。产品质量,生产线保证一致的,可控的产品质量,当然与工艺大师精雕细琢的艺术品不能比,总是比一般手工作坊要强得多。生产线上的工人,一般也成不了工艺大师,个人特别努力的除外。

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

使用道具 举报

回复
论坛徽章:
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
214#
发表于 2009-2-11 01:13 | 只看该作者
我用你给我的TJ01.TXT作试验,建立了TJRB表,主键为(TJDATE,UNIT,TABNAME,FLG):

DECLARE
   lv_f utl_file.file_type;
   lv_data VARCHAR2(1000);
BEGIN
   lv_f := UTL_FILE.FOPEN ('TJRB','TJ01.txt','r');
   LOOP
      BEGIN
         UTL_FILE.GET_LINE (lv_f,lv_data,1000);
      EXCEPTION
         WHEN NO_DATA_FOUND THEN
              EXIT;
      END;
      
      BEGIN
         INSERT INTO TJRB VALUES (
                TO_DATE(REGEXP_SUBSTR(lv_data,'[^|]+',1,1),'YYYY.MM.DD')
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1, 2)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1, 3)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1, 4)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1, 5)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1, 6)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1, 7)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1, 8)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1, 9)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,10)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,11)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,12)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,13)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,14)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,15)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,16)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,17)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,18)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,19)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,20)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,21)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,22)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,23)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,24)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,25)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,26)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,27)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,28)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,29)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,30)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,31)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,32)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,33)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,34)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,35)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,36)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,37)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,38)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,39)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,40)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,41)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,42)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,43)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,44)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,45)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,46)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,47)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,48)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,49)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,50)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,51)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,52)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,53)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,54)
               );
      EXCEPTION
         WHEN DUP_VAL_ON_INDEX THEN
              --UPDATE TJRB SET DAT1 = DAT1
              --WHERE TJDATE   =TO_DATE(REGEXP_SUBSTR(lv_data,'[^|]+',1,1),'YYYY.MM.DD')
              --      AND UNIT     =REGEXP_SUBSTR(lv_data,'[^|]+',1, 2)                        
              --      AND TABNAME  =REGEXP_SUBSTR(lv_data,'[^|]+',1, 3)                        
              --      AND FLG      =REGEXP_SUBSTR(lv_data,'[^|]+',1, 4);

              NULL;
      END;
   END LOOP;
   UTL_FILE.FCLOSE(lv_f);
END;
/

第一遍(空表,不出错):
Elapsed: 00:00:05.29

SELECT COUNT(*) FROM TJRB;

  COUNT(*)
----------
      1145

第二遍(把UPDATE注释掉。每行会报一个错,被捕获并忽略):
Elapsed: 00:00:26.77

第三遍(执行UPDATE):
Elapsed: 00:00:25.82

第四遍(恢复第二遍的程序,把UPDATE注释掉):
Elapsed: 00:00:25.49

在我这里没有什么灵异现象。UPDATE很快,加与不加没什么区别,那是ORACLE的本事。
当发生主键重复的EXCEPTION,内部有一个ROLLBACK, 这是速度下降的原因。

但系统的可维护性和易变更性是我们的不变需求。

跟是否用存储过程没有矛盾,我用PLSQL编程仍然可以做到可维护性和易变更性。

数据与程序独立,是几十年前提出的,至今仍是我的理想。

那你说为什么OO编程要把数据和程序封装到一个对象里?
如果你说的是“数据库”与“应用程序”独立,前面我已经给了TOM的链接说明为什么不可取了。

框架的意义在于20/80法则,……

你那80%的代码,如果改用存储过程实现,代价并不会更大。SQL和PLSQL比C更容易掌握,就看你愿不愿意花时间了。而SQL的威力是令人赞叹的,有时候一小段简洁优雅的SQL胜过一大堆段的程序!

使用道具 举报

回复
论坛徽章:
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
215#
 楼主| 发表于 2009-2-11 14:02 | 只看该作者

回复 #221 newkid 的帖子

我给你的TJ01.txt是3661行,不知为何只加了1145,你给精简了?
我加7552只用1.4秒,你用5.2秒可能因为regexp的原因?我是用DAU_dispack(),可能开销要比regexp要低(我只一趟扫描,你扫了54次)。还一个原因,我是打开了插入游标,每次插入彻底排除了语句分析和执行计划,甚至连bind都免了(第一次bind把所有列指向DAU内的数据记录),每次直接exec。你可以仿制,但程序很麻烦,不象DAU,都包好了,不用你管。
我有两种模式,真update,要把没插入的数据全部update进去,5.6秒。
假update,没有你那个好,是先select再update,7.7秒,用你那样的,可能也在5秒以内(都是以7552为准)。
为了排除机器性能方面的差异,给一个SQLloader的数据:
7552是1.2秒。3661是0.7秒。
程序与SQLloader性能之比为0.83.
你也做一个过程与SQLloader性能之比,这样比较公平。

你也确实发生重码变慢,由5.2秒变为25秒左右,之所以没出现怪异现象,是因为你那里update没有提速作用,而在我这里,变慢很严重,update居然发生了提速作用,那可真是ORACLE的本事。rollback和commit都试了,与时间无关。
其中机制还的研究和思考。但肯定与包装器无关,因为其他没有使用包装器的程序也出现重码变慢情况。14页139楼你的结果也是丢失时间50秒。我查遍这个帖子,没找到你的SQLloader这个文件的成功时间,但有个地方你说了用0.几秒。可以用 time sqlldr ........测试。但是根据5.2秒加载1145,与SQLloader(0.几秒)比值是差了一点。

通用性不必争论了,我这个程序已经为我加载好几个表了,你需要为每个表写加载。

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

使用道具 举报

回复
论坛徽章:
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
216#
 楼主| 发表于 2009-2-11 20:54 | 只看该作者
原帖由 newkid 于 2009-2-11 01:13 发表
我用你给我的TJ01.TXT作试验,建立了TJRB表,主键为(TJDATE,UNIT,TABNAME,FLG):

DECLARE
   lv_f utl_file.file_type;
   lv_data VARCHAR2(1000);
BEGIN
   lv_f := UTL_FILE.FOPEN ('TJRB','TJ01.txt','r');
   LOOP
      BEGIN
         UTL_FILE.GET_LINE (lv_f,lv_data,1000);
      EXCEPTION
         WHEN NO_DATA_FOUND THEN
              EXIT;
      END;
      
      BEGIN
         INSERT INTO TJRB VALUES (
                TO_DATE(REGEXP_SUBSTR(lv_data,'[^|]+',1,1),'YYYY.MM.DD')
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1, 2)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1, 3)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1, 4)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1, 5)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1, 6)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1, 7)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1, 8)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1, 9)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,10)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,11)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,12)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,13)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,14)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,15)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,16)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,17)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,18)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,19)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,20)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,21)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,22)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,23)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,24)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,25)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,26)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,27)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,28)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,29)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,30)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,31)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,32)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,33)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,34)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,35)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,36)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,37)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,38)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,39)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,40)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,41)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,42)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,43)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,44)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,45)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,46)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,47)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,48)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,49)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,50)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,51)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,52)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,53)
               ,REGEXP_SUBSTR(lv_data,'[^|]+',1,54)
               );
      EXCEPTION
         WHEN DUP_VAL_ON_INDEX THEN
              --UPDATE TJRB SET DAT1 = DAT1
              --WHERE TJDATE   =TO_DATE(REGEXP_SUBSTR(lv_data,'[^|]+',1,1),'YYYY.MM.DD')
              --      AND UNIT     =REGEXP_SUBSTR(lv_data,'[^|]+',1, 2)                        
              --      AND TABNAME  =REGEXP_SUBSTR(lv_data,'[^|]+',1, 3)                        
              --      AND FLG      =REGEXP_SUBSTR(lv_data,'[^|]+',1, 4);

              NULL;
      END;
   END LOOP;
   UTL_FILE.FCLOSE(lv_f);
END;
/

第一遍(空表,不出错):
Elapsed: 00:00:05.29

SELECT COUNT(*) FROM TJRB;

  COUNT(*)
----------
      1145

第二遍(把UPDATE注释掉。每行会报一个错,被捕获并忽略):
Elapsed: 00:00:26.77

第三遍(执行UPDATE):
Elapsed: 00:00:25.82

第四遍(恢复第二遍的程序,把UPDATE注释掉):
Elapsed: 00:00:25.49

在我这里没有什么灵异现象。UPDATE很快,加与不加没什么区别,那是ORACLE的本事。
当发生主键重复的EXCEPTION,内部有一个ROLLBACK, 这是速度下降的原因。


跟是否用存储过程没有矛盾,我用PLSQL编程仍然可以做到可维护性和易变更性。


那你说为什么OO编程要把数据和程序封装到一个对象里?
如果你说的是“数据库”与“应用程序”独立,前面我已经给了TOM的链接说明为什么不可取了。


你那80%的代码,如果改用存储过程实现,代价并不会更大。SQL和PLSQL比C更容易掌握,就看你愿不愿意花时间了。而SQL的威力是令人赞叹的,有时候一小段简洁优雅的SQL胜过一大堆段的程序!

那你说为什么OO编程要把数据和程序封装到一个对象里?
JAVA也提供了反射机制,照样提供了容器类、抽象类、泛型,支持独立程序,否则公共操作怎么做呢?

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

使用道具 举报

回复
论坛徽章:
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
217#
发表于 2009-2-11 23:51 | 只看该作者
确实文件不是原始的那个,时间太久我也忘记当时为什么修改了。我找出3776行的文件,空表插入的时间是:
00:00:15.08
不带UPDATE:
00:01:18.66
UPDATE:
00:01:18.82

我优化了一下程序,去掉规则表达式,仍然在空表运行:
DECLARE
   lv_f utl_file.file_type;
   lv_data VARCHAR2(1000);
   TYPE t_str IS TABLE OF VARCHAR2(1000) INDEX BY BINARY_INTEGER ;
   lv_cnt NUMBER :=0;
   lv_str t_str;
BEGIN
   lv_f := UTL_FILE.FOPEN ('TJRB','TJ01.txt','r');
   LOOP
      BEGIN
         UTL_FILE.GET_LINE (lv_f,lv_data,1000);
      EXCEPTION
         WHEN NO_DATA_FOUND THEN
              EXIT;
      END;
      lv_cnt := lv_cnt+1;
      lv_str(lv_cnt):=lv_data;
   END LOOP;
   UTL_FILE.FCLOSE(lv_f);
   
   FORALL i IN 1..lv_cnt
         INSERT INTO TJRB VALUES (
                TO_DATE(SUBSTR(lv_str(i),1,INSTR(lv_str(i),'|',1)-1),'YYYY.MM.DD')
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1, 1)+1,INSTR(lv_str(i),'|',1, 2) - INSTR(lv_str(i),'|',1, 1) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1, 2)+1,INSTR(lv_str(i),'|',1, 3) - INSTR(lv_str(i),'|',1, 2) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1, 3)+1,INSTR(lv_str(i),'|',1, 4) - INSTR(lv_str(i),'|',1, 3) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1, 4)+1,INSTR(lv_str(i),'|',1, 5) - INSTR(lv_str(i),'|',1, 4) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1, 5)+1,INSTR(lv_str(i),'|',1, 6) - INSTR(lv_str(i),'|',1, 5) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1, 6)+1,INSTR(lv_str(i),'|',1, 7) - INSTR(lv_str(i),'|',1, 6) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1, 7)+1,INSTR(lv_str(i),'|',1, 8) - INSTR(lv_str(i),'|',1, 7) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1, 8)+1,INSTR(lv_str(i),'|',1, 9) - INSTR(lv_str(i),'|',1, 8) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1, 9)+1,INSTR(lv_str(i),'|',1,10) - INSTR(lv_str(i),'|',1, 9) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,10)+1,INSTR(lv_str(i),'|',1,11) - INSTR(lv_str(i),'|',1,10) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,11)+1,INSTR(lv_str(i),'|',1,12) - INSTR(lv_str(i),'|',1,11) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,12)+1,INSTR(lv_str(i),'|',1,13) - INSTR(lv_str(i),'|',1,12) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,13)+1,INSTR(lv_str(i),'|',1,14) - INSTR(lv_str(i),'|',1,13) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,14)+1,INSTR(lv_str(i),'|',1,15) - INSTR(lv_str(i),'|',1,14) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,15)+1,INSTR(lv_str(i),'|',1,16) - INSTR(lv_str(i),'|',1,15) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,16)+1,INSTR(lv_str(i),'|',1,17) - INSTR(lv_str(i),'|',1,16) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,17)+1,INSTR(lv_str(i),'|',1,18) - INSTR(lv_str(i),'|',1,17) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,18)+1,INSTR(lv_str(i),'|',1,19) - INSTR(lv_str(i),'|',1,18) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,19)+1,INSTR(lv_str(i),'|',1,20) - INSTR(lv_str(i),'|',1,19) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,20)+1,INSTR(lv_str(i),'|',1,21) - INSTR(lv_str(i),'|',1,20) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,21)+1,INSTR(lv_str(i),'|',1,22) - INSTR(lv_str(i),'|',1,21) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,22)+1,INSTR(lv_str(i),'|',1,23) - INSTR(lv_str(i),'|',1,22) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,23)+1,INSTR(lv_str(i),'|',1,24) - INSTR(lv_str(i),'|',1,23) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,24)+1,INSTR(lv_str(i),'|',1,25) - INSTR(lv_str(i),'|',1,24) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,25)+1,INSTR(lv_str(i),'|',1,26) - INSTR(lv_str(i),'|',1,25) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,26)+1,INSTR(lv_str(i),'|',1,27) - INSTR(lv_str(i),'|',1,26) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,27)+1,INSTR(lv_str(i),'|',1,28) - INSTR(lv_str(i),'|',1,27) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,28)+1,INSTR(lv_str(i),'|',1,29) - INSTR(lv_str(i),'|',1,28) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,29)+1,INSTR(lv_str(i),'|',1,30) - INSTR(lv_str(i),'|',1,29) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,30)+1,INSTR(lv_str(i),'|',1,31) - INSTR(lv_str(i),'|',1,30) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,31)+1,INSTR(lv_str(i),'|',1,32) - INSTR(lv_str(i),'|',1,31) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,32)+1,INSTR(lv_str(i),'|',1,33) - INSTR(lv_str(i),'|',1,32) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,33)+1,INSTR(lv_str(i),'|',1,34) - INSTR(lv_str(i),'|',1,33) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,34)+1,INSTR(lv_str(i),'|',1,35) - INSTR(lv_str(i),'|',1,34) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,35)+1,INSTR(lv_str(i),'|',1,36) - INSTR(lv_str(i),'|',1,35) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,36)+1,INSTR(lv_str(i),'|',1,37) - INSTR(lv_str(i),'|',1,36) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,37)+1,INSTR(lv_str(i),'|',1,38) - INSTR(lv_str(i),'|',1,37) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,38)+1,INSTR(lv_str(i),'|',1,39) - INSTR(lv_str(i),'|',1,38) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,39)+1,INSTR(lv_str(i),'|',1,40) - INSTR(lv_str(i),'|',1,39) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,40)+1,INSTR(lv_str(i),'|',1,41) - INSTR(lv_str(i),'|',1,40) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,41)+1,INSTR(lv_str(i),'|',1,42) - INSTR(lv_str(i),'|',1,41) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,42)+1,INSTR(lv_str(i),'|',1,43) - INSTR(lv_str(i),'|',1,42) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,43)+1,INSTR(lv_str(i),'|',1,44) - INSTR(lv_str(i),'|',1,43) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,44)+1,INSTR(lv_str(i),'|',1,45) - INSTR(lv_str(i),'|',1,44) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,45)+1,INSTR(lv_str(i),'|',1,46) - INSTR(lv_str(i),'|',1,45) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,46)+1,INSTR(lv_str(i),'|',1,47) - INSTR(lv_str(i),'|',1,46) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,47)+1,INSTR(lv_str(i),'|',1,48) - INSTR(lv_str(i),'|',1,47) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,48)+1,INSTR(lv_str(i),'|',1,49) - INSTR(lv_str(i),'|',1,48) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,49)+1,INSTR(lv_str(i),'|',1,50) - INSTR(lv_str(i),'|',1,49) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,50)+1,INSTR(lv_str(i),'|',1,51) - INSTR(lv_str(i),'|',1,50) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,51)+1,INSTR(lv_str(i),'|',1,52) - INSTR(lv_str(i),'|',1,51) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,52)+1,INSTR(lv_str(i),'|',1,53) - INSTR(lv_str(i),'|',1,52) -1)
               ,SUBSTR(lv_str(i),INSTR(lv_str(i),'|',1,53)+1,INSTR(lv_str(i),'|',1,54) - INSTR(lv_str(i),'|',1,53) -1)
               );                                      
END;
/

00:00:01.40

SELECT COUNT(*) FROM TJRB;

  COUNT(*)
----------
      3776

总共是1.4秒。可见规则表达式很昂贵。至于你说的“打开了插入游标,每次插入彻底排除了语句分析和执行计划……”云云,这在PLSQL是完全自动实现的,我根步不用操心。
FORALL的异常处理比较罗嗦我就不做了。

我知道你一早就在鼓动我写程序和你的加载工具比,和SQLLDR比。但我一直没有动手,原因:
1. PLSQL是解释型语言,它的文件处理和字符解析肯定弱于C, 而且只能读取服务端的文件, 局限性太大;
2. 明摆着有更好的方法(但不是你的包装器!)
3. 这事情没有任何趣味和挑战性

我之所以写了这段代码不是要和你比拼速度,而是想看看你说的灵异现象到底是否存在。
我可以有99%把握地说,所谓“UPDATE提速”的问题还是在你的程序。
你应该看看我的第二条建议。你不是调用了updaterec就提速吗?那么,updaterec里面到底是哪一部分代码造成提速?
不是我吹牛,这现象要是发生在我的程序,我一会儿功夫就会调查清楚。

使用道具 举报

回复
论坛徽章:
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
218#
发表于 2009-2-12 05:00 | 只看该作者
刚刚闲着无聊把那个文件翻番变成7552行,作一个空表INSERT: 2.8秒; (我这机器比较老你可以在你的环境运行看看比你的C程序慢多少)

把程序改写一下,用 FORALL 再 MERGE INTO TJRB:
3.2秒 (空表, 或者非空都差不多)

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
219#
 楼主| 发表于 2009-2-12 09:21 | 只看该作者
原帖由 newkid 于 2009-2-12 05:00 发表
刚刚闲着无聊把那个文件翻番变成7552行,作一个空表INSERT: 2.8秒; (我这机器比较老你可以在你的环境运行看看比你的C程序慢多少)

把程序改写一下,用 FORALL 再 MERGE INTO TJRB:
3.2秒 (空表, 或者非空都差不多)

MERGE 是非常强大的。

给你一个7552的吧,把那个3661简单翻倍会重码。

TJ.rar

265.03 KB, 下载次数: 5

使用道具 举报

回复
论坛徽章:
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
220#
 楼主| 发表于 2009-2-12 09:57 | 只看该作者
原帖由 newkid 于 2009-2-12 05:00 发表
刚刚闲着无聊把那个文件翻番变成7552行,作一个空表INSERT: 2.8秒; (我这机器比较老你可以在你的环境运行看看比你的C程序慢多少)

把程序改写一下,用 FORALL 再 MERGE INTO TJRB:
3.2秒 (空表, 或者非空都差不多)

MERGE 是非常强大的。


没看懂你的程序,贴过来空表执行,出错:
:~/test> ora <ldtj.sql

SQL*Plus: Release 10.2.0.3.0 - Production on Thu Feb 12 09:33:34 2009

Copyright (c) 1982, 2006, Oracle.  All Rights Reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options

SQL>   2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25   26   27   28   29   30   31   32   33   34   35   36   37   38   39   40   41   42   43   44   45   46   47   48   49   50   51   52   53   54   55   56   57   58   59   60   61   62   63   64   65   66   67   68   69   70   71   72   73   74   75   76   77   78   79  DECLARE
*
ERROR at line 1:
ORA-29280: invalid directory path
ORA-06512: at "SYS.UTL_FILE", line 33
ORA-06512: at "SYS.UTL_FILE", line 436
ORA-06512: at line 8


SQL> SQL> Disconnected from Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options

8行是:
lv_f := UTL_FILE.FOPEN ('TJRB','TJ.txt','r');-- 哦,TJ.txt是我的文件,TJRB是什么?表名?
文件存在,可读写。检查是否粘错什么字符了,没发现。
文件中的436,33行删除,照旧。
改成这样也不对:lv_f := UTL_FILE.FOPEN ('/home/tuxticket/test','TJ.txt','r');
tuxticket@jgbticket:~/test> ls -l TJ.txt
-rw-r--r-- 1 tuxticket users 1163619 Dec 31 09:11 TJ.txt

改成这样:
  create or replace directory TJRB
          as '/home/tuxticket/test';

   lv_f := UTL_FILE.FOPEN ('TJRB','TJ.txt','r');
还是不行:
> ora <ldtj.sql

SQL*Plus: Release 10.2.0.3.0 - Production on Thu Feb 12 11:08:45 2009

Copyright (c) 1982, 2006, Oracle.  All Rights Reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options

SQL>   2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25   26   27   28   29   30   31   32   33   34   35   36   37   38   39   40   41   42   43   44   45   46   47   48   49   50   51   52   53   54   55   56   57   58   59   60   61   62   63   64   65   66   67   68   69   70   71   72   73   74   75   76   77   78   79   80   81   82       create or replace directory TJRB
        *
ERROR at line 8:
ORA-06550: line 8, column 2:
PLS-00103: Encountered the symbol "CREATE" when expecting one of the following:
begin case declare exit for goto if loop mod null pragma
raise return select update while with <an identifier>
<a double-quoted delimited-identifier> <a bind variable> <<
close current delete fetch lock insert open rollback
savepoint set sql execute commit forall merge pipe




update提速的问题,确实按你的要求,删除updaterec,用ret=1(正常返回值)代替,就是慢了。有update的时候,确实是正常修改了,我放了一些变动的数据确实改过来了。我再有错,打死我也想不出来怎么给人家提速。
merge我承认是好东西,但真正的业务不像加载那么简单,还是依赖常规的I,S,U,D操作,这个demo还是要给未来的ISUD操作给出一个测试依据。
sqlldr和merge是我们的标杆,看看我们到底功力如何,当然不可能有十成功力,8成就不错了。

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

使用道具 举报

回复

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

本版积分规则 发表回复

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