楼主: 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
531#
 楼主| 发表于 2010-8-25 10:07 | 只看该作者

回复 #539 yulihua49 的帖子

现在来个公平的:
time ./ldtj.sh

SQL*Loader: Release 10.2.0.3.0 - Production on Wed Aug 25 09:55:07 2010

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

specified value for readsize(10000000) less than bindsize(14000000)
Commit point reached - logical record count 1004
Commit point reached - logical record count 2008
Commit point reached - logical record count 3012
Commit point reached - logical record count 4016
Commit point reached - logical record count 5020
Commit point reached - logical record count 6024
Commit point reached - logical record count 7028
Commit point reached - logical record count 7552

real    0m0.991s
user    0m0.400s
sys     0m0.032s

Space allocated for bind array:               13987728 bytes(1004 rows)
Read   buffer bytes:14000000

Total logical records skipped:          0
Total logical records read:          7552
Total logical records rejected:         0
Total logical records discarded:        0

Run began on Wed Aug 25 09:55:07 2010
Run ended on Wed Aug 25 09:55:08 2010

Elapsed time was:     00:00:00.97
CPU time was:         00:00:00.41
它对这数据的加载能力是 7785行/秒。
原来我的程序是只commit1次,为更加公平,我也改1000条一次。
这样我纯耗时0.357秒,全耗时0.505秒。
每秒加载21154行。
DAU的速度是sqlldr的近3倍,不夸张吧?

[ 本帖最后由 yulihua49 于 2010-8-25 10: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
532#
 楼主| 发表于 2010-8-25 10:14 | 只看该作者

回复 #540 yulihua49 的帖子

现全文发表t_OAD程序,处理任意的表,是否够简单,有何需要改进?大家提意见。

  1. #include <DAU.h>
  2. #include <OAD.h>

  3. #define BATCH_NUM 1000
  4. /* 插入重码就修改
  5. 返回小于0出错,在SQL_Connect里
  6. >=0插入的条数   
  7. */
  8. static int upd,loss;
  9. //批量插入,遇重码修改之。在很多重码的场合,效率相当低
  10. int insert_DAO(OAD *oad,int n,DAU *DP)
  11. {
  12. char *p;
  13. char stmt[4096];
  14. int cc,ret,num;
  15. int beg;

  16.         beg=
  17.         ret=num=0;
  18.   do {
  19.         ret=OAD_exec(oad,beg,n);//真正的数组插入,就这一句。其余是错误处理
  20.         if(ret>0) num+=ret;
  21.         if(ret == n-beg) return num;
  22.         if(oad->SQL_Connect->Errno != DUPKEY) {
  23.                 ShowLog(1,"%s:OAD_exec err=%d,%s",__FUNCTION__,
  24.                         oad->SQL_Connect->Errno,
  25.                         oad->SQL_Connect->ErrMsg);
  26.                 return ret;
  27.         }
  28.         if(ret<0) ret=0;
  29.         p=(char *)oad->recs;
  30.         p+=(beg+ret)*(oad->reclen);
  31.         memcpy(DP->srm.rec,p,oad->reclen);
  32.         *stmt=0;
  33.         cc=update_by_PK(DP,stmt);
  34.         if(cc<=0) {
  35.                 ShowLog(1,"%s update stmt=%s,err=%d,%s",__FUNCTION__,
  36.                         stmt,
  37.                         oad->SQL_Connect->Errno,
  38.                         oad->SQL_Connect->ErrMsg);
  39.                 return 0;
  40.         }
  41.         upd+=cc;
  42.         beg+=ret+1;
  43. //ShowLog(5,"%s:beg=%d",__FUNCTION__,beg);
  44.   } while(beg<n);
  45.         return num;
  46. }

  47. int loadfile(T_SQL_Connect *SQL_Connect,char *tablename,FILE *ifd,FILE *ofd,int Pflg,char *buf,int buflen)
  48. {
  49. char *p,tabn[512];
  50. DAU _DAU;
  51. OAD oad;
  52. int rows,ret;
  53. int n,num;
  54. INT64 now;

  55.     ShowLog(5,"loadfile:entry");
  56.         now=now_usec();
  57.     ret=DAU_init(&_DAU,SQL_Connect,tablename,0,0);
  58.     if(ret) {
  59.         ShowLog(1,"loadfile:DAU_init tabname=%s,ret=%d",tablename,ret);
  60.         return -1;
  61.     }
  62.         num=_DAU.srm.tp[_DAU.srm.Aflg].offset;
  63. char recs[BATCH_NUM * num];
  64.         ShowLog(5,"DAU_init ret=%d,TIMEVAL=%ld,reclen=%d,size=%d",ret,now_usec()-now,num,sizeof(recs));
  65.         OAD_init(&oad,&_DAU,recs,BATCH_NUM);
  66.         upd=loss=0;
  67.         *buf=0;
  68.         ret=OAD_mk_ins(&oad,buf);
  69.         if(ret) {
  70.                 ShowLog(1,"aft OAD_mk_ins:stmt=%s,err=%d,%s\n",buf,
  71.                         SQL_Connect->Errno,
  72.                         SQL_Connect->ErrMsg);
  73.                         OAD_free(&oad);
  74.                         DAU_free(&_DAU);
  75.                         return -1;
  76.         }
  77.         n=num=0;
  78.         now=now_usec();
  79.     for(rows=0;!ferror(ifd);) {
  80.         fgets(buf,buflen,ifd);
  81.         if(feof(ifd)) break;

  82.                 OAD_pkg_dispack(&oad,n,buf,'|');
  83.                 if(BATCH_NUM == ++n) {
  84.                         ret=insert_DAO(&oad,n,&_DAU);
  85.                          ___SQL_Transaction__(SQL_Connect,TRANCOMMIT);
  86.                         n=0;
  87.                         if(ret<0) break;
  88.                         rows += ret;
  89.                 }
  90.        }
  91.         if(n) {
  92.                         ret=insert_DAO(&oad,n,&_DAU);
  93.                         if(ret>0) rows += ret;
  94.                         n=0;
  95.         }
  96.     ShowLog(2,"loadfile:rows=%d,upd=%d,TIMEVAL=%lld",rows,upd,now_usec()-now);
  97.         OAD_free(&oad);
  98.         DAU_free(&_DAU);
  99.         return rows;
  100. }

  101. static char my_showid[200];
  102. #define DEF_BUF_SIZ 4096
  103. main(int argc,char *argv[])
  104. {
  105. int ret,i,len=DEF_BUF_SIZ;
  106. T_SQL_Connect SQL_Connect;
  107. int Pflg=0;
  108. char *tabname=0;
  109. FILE *ifd,*ofd;
  110. INT64 now;
  111. char *myname;

  112.     tzset();
  113.     myname=sc_basename(argv[0]);
  114.     sprintf(my_showid,"%s:%d",
  115.         myname,getpid());
  116.     Showid=my_showid;
  117.     ifd=0;
  118.     ofd=0;

  119. /*******************************************************************
  120. *  get Opt
  121. *******************************************************************/
  122.     for(i=1;i<argc;i++) {
  123.         if(*argv[i]=='-') {
  124.             switch(argv[i][1]) {
  125.             case 'f':
  126.                 if(argv[i][2]) ret=envcfg(argv[i]+2);
  127.                 else {
  128.                     i++;
  129.                     ret=envcfg(argv[i]);
  130.                 }
  131.                 continue;
  132.             case 'P':  //输出 不能加载的记录
  133.                 Pflg=1;
  134.                 if(argv[i][2]) {
  135.                     ofd=fopen(argv[i]+2,"w");
  136.                 } else {
  137.                     i++;
  138.                     if(i<argc) ofd=fopen(argv[i],"w");
  139.                 }
  140.                 continue;
  141.             case 'K':  //设置工作buff,Kbyte。
  142.                 Pflg=1;
  143.                 if(argv[i][2]) {
  144.                     len=atoi(argv[i]+2);
  145.                 } else {
  146.                     i++;
  147.                     if(i<argc) len=atoi(argv[i]);;
  148.                 }
  149.                 continue;
  150.             default:
  151.                 fprintf(stderr,"no know option:%s",argv[i]);
  152.                 fprintf(stderr,"Usage:%s -f 配置文件 [-P] 输出文件名 [-Kkbytes] [-W]WHERE 子句 [-D]执行日期 [-d]作业日期\n",
  153.                     argv[0]);
  154.                 continue;
  155.             }
  156.         }
  157.         tabname=argv[i];
  158.     }
  159.     if(len < DEF_BUF_SIZ) len=DEF_BUF_SIZ;
  160. char buf[len];
  161.     *buf=0;

  162. ShowLog(5,"tabname=%s",tabname);
  163.     ret=db_open(&SQL_Connect);
  164.     if(ret) {
  165.         ShowLog(1,"Open Database err=%d.%s",
  166.             SQL_Connect.Errno,
  167.             SQL_Connect.ErrMsg);
  168.         return 1;
  169.     }
  170. ShowLog(5,"DB=%s",SQL_Connect.DBOWN);
  171.     if(!ofd) ofd=stdout;
  172.     ifd=stdin;

  173.     now=now_usec();
  174. int cc;
  175.         ret=loadfile(&SQL_Connect,tabname,ifd,ofd,Pflg,buf,sizeof(buf));
  176.         ShowLog(2,"loadasc:load %d rec's time=%ld,buf=%s",ret,(long)(now_usec()-now),buf);
  177.                 now=now_usec();
  178.                 cc=___SQL_Transaction__(&SQL_Connect,TRANCOMMIT);
  179. ShowLog(5,"loadfile:%d commit TIMEVAL=%lld,ret=%d",ret,now_usec()-now,cc);

  180.     if(ofd && ofd != stdout) fclose(ofd);
  181.     ret=___SQL_CloseDatabase__(&SQL_Connect);
  182.     return 0;
  183. }
复制代码


包装器提高效率的秘诀:耗时的操作在init里完成,给后续数据作业创造条件,数据操作时的开销极小。
这里我们看一下那个最频繁使用的OAD_exec:
int OAD_exec(OAD *oad,int begin,int n)
{
int ret;

        oad->begin=begin;
        oad->rows=(n<=(oad->max_rows_of_batch-begin))?nad->max_rows_of_batch-begin;
        if(!begin) { //只有原始的执行如此
//ShowLog(5,"%s:tabname=%s",__FUNCTION__,oad->srm->tabname);
                BB_Tree_Scan(oad->bind_tree,bind_data);
        }
        ret=sqlo_execute1(oad->sth,oad->begin,n);
        if(ret) {
                ___SQL_GetError(oad->SQL_Connect);
                return -1;
        }
        if(oad->a_col_flg) BB_Tree_Scan(oad->bind_tree,get_ret);//如果有RETURNING变量,取回。
        return sqlo_prows(oad->sth);
}
这个包装干了什么?
通过二叉树检查一下数据的NULL情况,设置表示器变量。(如果你自己做,这一步很可能遗漏哦!)
然后就是执行sqlo_exec了,最后取出成功行数。
就这么简单,效率想不高都难。

为什么比sqlldr效率高?因为它使用字符绑定,要每次都绑定变量。而我,一次绑定,多次使用。这得益于DAU内部使用结构,数据已经按类型放在固定的地方。这里回答了newkid的质问,这样的应用为何要使用结构?绑定变量开销很大的。

[ 本帖最后由 yulihua49 于 2010-8-25 12:43 编辑 ]

使用道具 举报

回复
论坛徽章:
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
533#
 楼主| 发表于 2010-8-25 11:05 | 只看该作者
原帖由 yulihua49 于 2010-8-25 10:07 发表
现在来个公平的:
time ./ldtj.sh

SQL*Loader: Release 10.2.0.3.0 - Production on Wed Aug 25 09:55:07 2010

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

specified value for readsize(10000000) less than bindsize(14000000)
Commit point reached - logical record count 1004
Commit point reached - logical record count 2008
Commit point reached - logical record count 3012
Commit point reached - logical record count 4016
Commit point reached - logical record count 5020
Commit point reached - logical record count 6024
Commit point reached - logical record count 7028
Commit point reached - logical record count 7552

real    0m0.991s
user    0m0.400s
sys     0m0.032s

Space allocated for bind array:               13987728 bytes(1004 rows)
Read   buffer bytes:14000000

Total logical records skipped:          0
Total logical records read:          7552
Total logical records rejected:         0
Total logical records discarded:        0

Run began on Wed Aug 25 09:55:07 2010
Run ended on Wed Aug 25 09:55:08 2010

Elapsed time was:     00:00:00.97
CPU time was:         00:00:00.41
它对这数据的加载能力是 7785行/秒。
原来我的程序是只commit1次,为更加公平,我也改1000条一次。
这样我纯耗时0.357秒,全耗时0.505秒。
每秒加载21154行。
DAU的速度是sqlldr的近3倍,不夸张吧?

当然,高性能应该归功于OCI,但可以说明,DAU的包装效率要高于sqlldr的包装效率。
而且,sqlldr只是个实用程序,DAU是个开发平台,它可以让你写出许许多多的高效率应用程序。

[ 本帖最后由 yulihua49 于 2010-8-25 11:08 编辑 ]

使用道具 举报

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

批量处理应用实例

static int ins_stop(OAD *OADP,DAU *DP,int num,char *stmt)
{
int ret;

        if(DP->del_sth < 0) DAU_mk_where(DP,"train_code",stmt);
        ret=DAU_delete(DP,stmt);//先删
        ShowLog(5,"%s次,del %d Rec's",((DL10_TRAINSTOPINFO_stu *)DP->srm.rec)->train_code,ret);
        ret=OAD_exec(OADP,0,num);//批量插入
        if(ret==num) ShowLog(2,"%s次 成功插入%d站",((DL10_TRAINSTOPINFO_stu *)DP->srm.rec)->train_code,ret);
        else ShowLog(1,"%s次,插入错误 %d,err=%d,%s",((DL10_TRAINSTOPINFO_stu *)DP->srm.rec)->train_code,
                ret,DP->SQL_Connect->Errno,DP->SQL_Connect->ErrMsg);
        return ret;
}

原先插入11000多记录用30秒,改批量后2.3秒。

从excel表读出数据,查站码计算运行图后插入数据库。

这个如果用存储过程,把若干车站的全部数据传给存储过程,有这功夫,活早干完了。每个车次少则2-3站,多则几十个停站,每记录19个列,叫我怎么往存储过程传?

解析xls的过程很复杂,存储过程干不了。解析结果在结构里,结构要进数据库。这活DAU最拿手了。

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

使用道具 举报

回复
论坛徽章:
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
535#
发表于 2010-8-25 21:59 | 只看该作者
被sqlldr忽悠了两年,它原来是成组插入的。
我的单条插入算法与他PK,达到83%的性能,我容易吗?

谁忽悠你了?我一开始就和你说过数组绑定呀?那时候你还没掌握这个杀手锏,连绑定变量你都反对呢,能怪谁?

还需要用存储过程PK一下?

那就来用存储过程+外部表PK一下,谁怕谁。前面好像写过了?
用了外部表,整个加载过程变成一个INSERT ... SELECT 的SQL, 你来和它比比看。
PLSQL读文件比C语言慢,本来它就不适合干这个,所以我不会用读文本+插入的方式。

DAU的速度是sqlldr的近3倍,不夸张吧?

它是个通用程序,解析的功能比你强得多,当然这地方会有损耗。什么时候你实现了SQLLDR的控制文件的所有解析功能再来PK不迟。


原先插入11000多记录用30秒,改批量后2.3秒。

从excel表读出数据,查站码计算运行图后插入数据库。

这个如果用存储过程,把若干车站的全部数据传给存储过程,有这功夫,活早干完了。每个车次少则2-3站,多则几十个停站,每记录19个列,叫我怎么往存储过程传?

解析xls的过程很复杂,存储过程干不了。解析结果在结构里,结构要进数据库。这活DAU最拿手了。

把EXCEL转成文本,放在数据库上,用外部表访问。用SQL做你的所有业务(查站码啦,计算运行图啦,插入表啦)。谁说存储过程干不了?不信把你的需求写出来试试!

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
536#
发表于 2010-8-26 00:31 | 只看该作者
lz做一个多线程并行插入?

使用道具 举报

回复
论坛徽章:
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
537#
 楼主| 发表于 2010-8-26 10:12 | 只看该作者
原帖由 〇〇 于 2010-8-26 00:31 发表
lz做一个多线程并行插入?

实际上那个程序就是多线程并行插入。4个线程并行(因为原始表是4组列并行)。使用了数据库连接池。
后来发现池里4个连接和1个链接总体运行时间是一样的,没有区别。后来连接池只放一个连接,4个线程争用。

现在的DAU是全功能ORA数据库开发平台,能处理复杂语句如RETURNING子句,多表关联操作,批量插入。线程安全,还有数据库连接池功能。
可以调用存储过程。blob数据可以调用底层实现。DAU没有封闭底层。

使用连接池的小例子:
  1. //准备数据单元,处理连接池
  2. static int store(TRN_MMNT_stu *trn_rec,int num,char *stmt)
  3. {
  4. T_SQL_Connect SQL_Connect;
  5. DAU trn_dau;
  6. int ret;
  7. INT64 now;
  8.         ___SQL_Init_SQL_Connect(&SQL_Connect);
  9.         ret=get_DB_connect(&SQL_Connect,poolno);
  10. now=now_usec();
  11.         if(ret) {
  12.                 ShowLog(1,"%s,DB ERROR=%d,%s",__FUNCTION__,
  13.                         SQL_Connect.Errno,
  14.                         SQL_Connect.ErrMsg);
  15.                 return -1;
  16.         }
  17.         DAU_init(&trn_dau,&SQL_Connect,0,trn_rec,TRN_MMNT_tpl);

  18.         ___SQL_Transaction__(&SQL_Connect,TRANBEGIN);
  19. //ShowLog(5,"mmnt dbh %d BEGIN TIMEVAL=%lld",SQL_Connect.dbh,now_usec()-now);
  20.         ret=store_data(&trn_dau,num,stmt);      //执行插入数据库
  21.         DAU_free(&trn_dau);
  22.         if(!ret) ___SQL_Transaction__(&SQL_Connect,TRANCOMMIT);
  23.         else {
  24.                 ___SQL_Transaction__(&SQL_Connect,TRANROLLBACK);
  25.                 sprintf(stmt+strlen(stmt)," err=%d,%s",SQL_Connect.Errno,SQL_Connect.ErrMsg);
  26.         }
  27. ShowLog(5,"mmnt %s:dbh=%d,num=%d,total TIMEVAL=%lld",__FUNCTION__,SQL_Connect.dbh,num,now_usec()-now);
  28.         release_DB_connect(&SQL_Connect,poolno);
  29.         return ret;
  30. }
复制代码

[ 本帖最后由 yulihua49 于 2010-8-26 11:14 编辑 ]

使用道具 举报

回复
论坛徽章:
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
538#
 楼主| 发表于 2010-8-26 10:15 | 只看该作者
原帖由 newkid 于 2010-8-25 21:59 发表

谁忽悠你了?我一开始就和你说过数组绑定呀?那时候你还没掌握这个杀手锏,连绑定变量你都反对呢,能怪谁?

它是个通用程序,解析的功能比你强得多,当然这地方会有损耗。什么时候你实现了SQLLDR的控制文件的所有解析功能再来PK不迟。



把EXCEL转成文本,放在数据库上,用外部表访问。用SQL做你的所有业务(查站码啦,计算运行图啦,插入表啦)。谁说存储过程干不了?不信把你的需求写出来试试!

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

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

[ 本帖最后由 yulihua49 于 2010-8-26 11:05 编辑 ]

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
539#
发表于 2010-8-26 10:15 | 只看该作者
那sqlldr是单进程?

使用道具 举报

回复
论坛徽章:
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
540#
 楼主| 发表于 2010-8-26 10:26 | 只看该作者
原帖由 〇〇 于 2010-8-26 10:15 发表
那sqlldr是单进程?

sqlldr是单进程,我那个t_OAD也是单进程。比赛是公平的。

使用道具 举报

回复

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

本版积分规则 发表回复

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