楼主: 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
481#
 楼主| 发表于 2010-3-1 09:40 | 只看该作者
原帖由 newkid 于 2010-2-23 23:47 发表
如果仅仅是数据加载,不涉及任何事务处理逻辑,映射到结构就没什么意义,一个二维数组就够了。你需要的只是一个缓存,从文件读入,再送给目标数据库。
通用的数据抽取转换工具已经很多了,我只要使用就行。

hibernate我们是不用的,看不到任何好处。我们大量使用存储过程。

好吧,给你一个不用DAU的OCI程序的例子,你就知道为什么要用结构映射了:


  1. #include<ocilib.h>
  2. #include<sys/time.h>

  3. long interval(struct timeval *begtime,struct timeval *endtime)
  4. {
  5. long ret;
  6.         ret=endtime->tv_sec-begtime->tv_sec;
  7.         ret*=1000000;
  8.         ret += endtime->tv_usec - begtime->tv_usec;
  9.         return ret;
  10. }

  11. static OCI_Connection *cn = NULL;
  12. static int nb_err=0;

  13. void err_handler(OCI_Error *err)
  14. {

  15.     if (OCI_ErrorGetType(err) == OCI_ERR_ORACLE)
  16.     {
  17.         const mtext *sql = OCI_GetSql(OCI_ErrorGetStatement(err));

  18.         if (sql != NULL)
  19.         {
  20.             fprintf(stderr,"> ERROR - SQL : %s\n",sql);
  21.         }
  22.     }

  23.     fprintf(stderr,">ERROR %d , MSG: %s\n",
  24.         OCI_ErrorGetOCICode(err),OCI_ErrorGetString(err));

  25.     nb_err++;
  26. }

  27. /* ------------------------------------------------------------------------ *
  28. * disconnect
  29. * ------------------------------------------------------------------------ */

  30. void disconnect(OCI_Connection *cn)
  31. {
  32.     OCI_ConnectionFree(cn);
  33. }

  34. void cleanup(void)
  35. {
  36.     OCI_Cleanup();
  37. }

  38. int loadfile(OCI_Connection *cn)
  39. {
  40. OCI_Statement  *st = NULL;
  41. OCI_Resultset  *rs = NULL;
  42. int ret,num=0;
  43. char buf[4096],*p;
  44. char *tok="|";
  45. struct timeval begtime,endtime;

  46.          gettimeofday(&begtime,0);
  47.         st = OCI_StatementCreate(cn);
  48.         ret=OCI_Prepare(st, "INSERT INTO TJRB "
  49.                             "(tjdate,unit,tabname,flg,"
  50.                             "dat1,dat2,dat3,dat4,dat5,dat6,dat7,dat8,dat9,"
  51.                         "dat10,dat11,dat12,dat13,dat14,dat15,dat16,dat17,dat18,dat19,"
  52.                         "dat20,dat21,dat22,dat23,dat24,dat25,dat26,dat27,dat28,dat29,"
  53.                         "dat30,dat31,dat32,dat33,dat34,dat35,dat36,dat37,dat38,dat39,"
  54.                         "dat40,dat41,dat42,dat43,dat44,dat45,dat46,dat47,dat48,dat49,"
  55.                         "dat50) VALUES (to_date(:tjdate,'YYYY-MM-DD'),:unit,:tabname,:flg,"
  56.                             ":dat1,:dat2,:dat3,:dat4,:dat5,:dat6,:dat7,:dat8,:dat9,"
  57.                         ":dat10,:dat11,:dat12,:dat13,:dat14,:dat15,:dat16,:dat17,:dat18,:dat19,"
  58.                         ":dat20,:dat21,:dat22,:dat23,:dat24,:dat25,:dat26,:dat27,:dat28,:dat29,"
  59.                         ":dat30,:dat31,:dat32,:dat33,:dat34,:dat35,:dat36,:dat37,:dat38,:dat39,"
  60.                         ":dat40,:dat41,:dat42,:dat43,:dat44,:dat45,:dat46,:dat47,:dat48,:dat49,"
  61.                         ":dat50)");
  62.          gettimeofday(&endtime,0);
  63. fprintf(stderr,"prepare TIMEVAL=%ld\n",interval(&begtime,&endtime));
  64.         if(ret != TRUE) return -1;

  65.         while(!ferror(stdin)) {
  66.                 fgets(buf,sizeof(buf),stdin);
  67.                 if(feof(stdin)) break;

  68.                 p=strtok(buf,tok);
  69.                 OCI_BindString(st,MT(":tjdate"),p,strlen(p)+1);
  70.                 p=strtok(0,tok);
  71.                 OCI_BindString(st,MT(":unit"),p,strlen(p)+1);
  72.                 p=strtok(0,tok);
  73.                 OCI_BindString(st,MT(":tabname"),p,strlen(p)+1);
  74.                 p=strtok(0,tok);
  75.                 OCI_BindString(st,MT(":flg"),p,strlen(p)+1);
  76.                 p=strtok(0,tok);
  77.                 OCI_BindString(st,MT(":dat1"),p,strlen(p)+1);
  78.                 p=strtok(0,tok);
  79.                 OCI_BindString(st,MT(":dat2"),p,strlen(p)+1);
  80.                 p=strtok(0,tok);
  81.                 OCI_BindString(st,MT(":dat3"),p,strlen(p)+1);
  82.                 p=strtok(0,tok);
  83.                 OCI_BindString(st,MT(":dat4"),p,strlen(p)+1);
  84.                 p=strtok(0,tok);
  85.                 OCI_BindString(st,MT(":dat5"),p,strlen(p)+1);
  86.                 p=strtok(0,tok);
  87.                 OCI_BindString(st,MT(":dat6"),p,strlen(p)+1);
  88.                 p=strtok(0,tok);
  89.                 OCI_BindString(st,MT(":dat7"),p,strlen(p)+1);
  90.                 p=strtok(0,tok);
  91.                 OCI_BindString(st,MT(":dat8"),p,strlen(p)+1);
  92.                 p=strtok(0,tok);
  93.                 OCI_BindString(st,MT(":dat9"),p,strlen(p)+1);
  94.                 p=strtok(0,tok);
  95.                 OCI_BindString(st,MT(":dat10"),p,strlen(p)+1);
  96.                 p=strtok(0,tok);
  97.                 OCI_BindString(st,MT(":dat11"),p,strlen(p)+1);
  98.                 p=strtok(0,tok);
  99.                 OCI_BindString(st,MT(":dat12"),p,strlen(p)+1);
  100.                 p=strtok(0,tok);
  101.                 OCI_BindString(st,MT(":dat13"),p,strlen(p)+1);
  102.                 p=strtok(0,tok);
  103.                 OCI_BindString(st,MT(":dat14"),p,strlen(p)+1);
  104.                 p=strtok(0,tok);
  105.                 OCI_BindString(st,MT(":dat15"),p,strlen(p)+1);
  106.                 p=strtok(0,tok);
  107.                 OCI_BindString(st,MT(":dat16"),p,strlen(p)+1);
  108.                 p=strtok(0,tok);
  109.                 OCI_BindString(st,MT(":dat17"),p,strlen(p)+1);
  110.                 p=strtok(0,tok);
  111.                 OCI_BindString(st,MT(":dat18"),p,strlen(p)+1);
  112.                 p=strtok(0,tok);
  113.                 OCI_BindString(st,MT(":dat19"),p,strlen(p)+1);
  114.                 p=strtok(0,tok);
  115.                 OCI_BindString(st,MT(":dat20"),p,strlen(p)+1);
  116.                 p=strtok(0,tok);
  117.                 OCI_BindString(st,MT(":dat21"),p,strlen(p)+1);
  118.                 p=strtok(0,tok);
  119.                 OCI_BindString(st,MT(":dat22"),p,strlen(p)+1);
  120.                 p=strtok(0,tok);
  121.                 OCI_BindString(st,MT(":dat23"),p,strlen(p)+1);
  122.                 p=strtok(0,tok);
  123.                 OCI_BindString(st,MT(":dat24"),p,strlen(p)+1);
  124.                 p=strtok(0,tok);
  125.                 OCI_BindString(st,MT(":dat25"),p,strlen(p)+1);
  126.                 p=strtok(0,tok);
  127.                 OCI_BindString(st,MT(":dat26"),p,strlen(p)+1);
  128.                 p=strtok(0,tok);
  129.                 OCI_BindString(st,MT(":dat27"),p,strlen(p)+1);
  130.                 p=strtok(0,tok);
  131.                 OCI_BindString(st,MT(":dat28"),p,strlen(p)+1);
  132.                 p=strtok(0,tok);
  133.                 OCI_BindString(st,MT(":dat29"),p,strlen(p)+1);
  134.                 p=strtok(0,tok);
  135.                 OCI_BindString(st,MT(":dat30"),p,strlen(p)+1);
  136.                 p=strtok(0,tok);
  137.                 OCI_BindString(st,MT(":dat31"),p,strlen(p)+1);
  138.                 p=strtok(0,tok);
  139.                 OCI_BindString(st,MT(":dat32"),p,strlen(p)+1);
  140.                 p=strtok(0,tok);
  141.                 OCI_BindString(st,MT(":dat33"),p,strlen(p)+1);
  142.                 p=strtok(0,tok);
  143.                 OCI_BindString(st,MT(":dat34"),p,strlen(p)+1);
  144.                 p=strtok(0,tok);
  145.                 OCI_BindString(st,MT(":dat35"),p,strlen(p)+1);
  146.                 p=strtok(0,tok);
  147.                 OCI_BindString(st,MT(":dat36"),p,strlen(p)+1);
  148.                 p=strtok(0,tok);
  149.                 OCI_BindString(st,MT(":dat37"),p,strlen(p)+1);
  150.                 p=strtok(0,tok);
  151.                 OCI_BindString(st,MT(":dat38"),p,strlen(p)+1);
  152.                 p=strtok(0,tok);
  153.                 OCI_BindString(st,MT(":dat39"),p,strlen(p)+1);
  154.                 p=strtok(0,tok);
  155.                 OCI_BindString(st,MT(":dat40"),p,strlen(p)+1);
  156.                 p=strtok(0,tok);
  157.                 OCI_BindString(st,MT(":dat41"),p,strlen(p)+1);
  158.                 p=strtok(0,tok);
  159.                 OCI_BindString(st,MT(":dat42"),p,strlen(p)+1);
  160.                 p=strtok(0,tok);
  161.                 OCI_BindString(st,MT(":dat43"),p,strlen(p)+1);
  162.                 p=strtok(0,tok);
  163.                 OCI_BindString(st,MT(":dat44"),p,strlen(p)+1);
  164.                 p=strtok(0,tok);
  165.                 OCI_BindString(st,MT(":dat45"),p,strlen(p)+1);
  166.                 p=strtok(0,tok);
  167.                 OCI_BindString(st,MT(":dat46"),p,strlen(p)+1);
  168.                 p=strtok(0,tok);
  169.                 OCI_BindString(st,MT(":dat47"),p,strlen(p)+1);
  170.                 p=strtok(0,tok);
  171.                 OCI_BindString(st,MT(":dat48"),p,strlen(p)+1);
  172.                 p=strtok(0,tok);
  173.                 OCI_BindString(st,MT(":dat49"),p,strlen(p)+1);
  174.                 p=strtok(0,tok);
  175.                 OCI_BindString(st,MT(":dat50"),p,strlen(p)+1);

  176.                 ret= OCI_Execute(st);
  177.                 OCI_BindFreeAll(st);
  178.                 if(ret==TRUE) num++;

  179.         }

  180.         OCI_StatementFree(st); //关闭游标
  181.         return num;
  182. }

  183. main(int argc ,char *argv[])
  184. {
  185. int ret;
  186. OCI_Error *err;
  187. struct timeval begtime,endtime;

  188.          gettimeofday(&begtime,0);
  189.          if (!OCI_Initialize(err_handler, NULL, OCI_ENV_DEFAULT))
  190.                 return 1;

  191.         cn = OCI_ConnectionCreate("ticket", "ticket", "ticket", OCI_SESSION_DEFAULT);
  192.          gettimeofday(&endtime,0);
  193. fprintf(stderr,"connect TIMEVAL=%ld\n",interval(&begtime,&endtime));
  194.         if(!cn) {
  195.                 fprintf(stderr,"OCI_ConnectionCreate Error\n");
  196.                 cleanup();
  197.                 return 2;
  198.         }
  199.         ret=loadfile(cn);
  200.          gettimeofday(&begtime,0);
  201.         if(ret<0) OCI_Rollback(cn);
  202.         else OCI_Commit(cn);
  203.          gettimeofday(&endtime,0);
  204. fprintf(stderr,"loadfile:%d commit TIMEVAL=%ld\n",ret,interval(&begtime,&endtime));

  205. //      disconnect(cn); //关闭一个连接
  206.         cleanup();      //关闭全部包括上一步
  207.         return 0;
  208. }

复制代码

比起48页478楼的例子,它只能加载我们前边说的tjrb表,还不能处理重码问题。
加载这个表(从空表),DAU的时间是1.1秒,这个程序是2.4秒,区别在于它没有用结构,每次从文件读入的行,每列的位置不固定,因此不能一次绑定,多次使用。
它也是保留游标的,但每次绑定变量,效率。。。。。。。

能不能写一个公用程序把列绑定到离散的变量里?这太难了,即使能够从数据库中分析表结构,你如何自动安排数十个不同类型的离散变量?动用一大堆malloc?如果传给其他函数处理?一大堆数目不定的自变量?怎么释放?因此通过结构映射是最方便的做法。

你也看到DAU的效率远高于直接的OCI,不是DAU高于OCI,而是我DIY的比你DIY高明。
哪个通用,哪个好懂,哪个省事,哪个高效。。。。。。

OCI程序不像存储过程,不能自动绑定变量,绑定的过程相当繁琐,所以如果不用DAU,许多OCI程序员就不玩绑定了。这就是DAU工具的重大意义。

处理业务逻辑,使用列名是不可避免的,但存取数据还要列举列名是多么痛苦的一件事,这个程序已经列举3遍了,还不包括对结构的映射。

hibernate,你不用,用的大有人在,火得很哦。包装简化了使用,即使损失些效率,也受欢迎。

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

使用道具 举报

回复
论坛徽章:
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
482#
发表于 2010-3-1 12:43 | 只看该作者
http://www.itpub.net/thread-1271979-5-1.html
c已经比cube快了,还能更快?

使用道具 举报

回复
论坛徽章:
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
483#
 楼主| 发表于 2010-3-1 14:25 | 只看该作者
原帖由 〇〇 于 2010-3-1 12:43 发表
http://www.itpub.net/thread-1271979-5-1.html
c已经比cube快了,还能更快?

你没有包括数据库读写。如果原始数据在数据库,你光是把它们读出来就已经比group  by cube慢了。
单纯看归并过程:
我那个树归并也比ORACLE慢,他可能是hash归并。我要是用hash可能达到他的速度,但hash表占用内存比较大。
树的逻辑比较简单,也比较通用。
你那个程序我不太懂,好像把3个列组装成一个key,也是一种hash法?冲突如何处理,null怎样解决?(替newkid问)。

[ 本帖最后由 yulihua49 于 2010-3-1 14:29 编辑 ]

使用道具 举报

回复
论坛徽章:
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
484#
 楼主| 发表于 2010-3-1 14:37 | 只看该作者

回复 #490 yulihua49 的帖子

从上述例子可以看出,与数据独立的、通用的程序,就一定比专用程序低效? DAU完全颠覆了这个传统观念。
希望有热爱OCI者上前PK!

使用道具 举报

回复
论坛徽章:
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
485#
发表于 2010-3-1 19:40 | 只看该作者
原帖由 yulihua49 于 2010-3-1 14:25 发表

你没有包括数据库读写。如果原始数据在数据库,你光是把它们读出来就已经比group  by cube慢了。

dcba老大的工具:
ibm01:/home/oracle$/tmp/sqluldr2_aix64_9208.bin a/a query="select * from t" file=/dev/null
       0 rows exported at 2010-02-26 17:08:55, size 0 MB.
1000000 rows exported at 2010-02-26 17:08:57, size 12 MB.
         output file /dev/null closed at 1000000 rows, size 16 MB.
连读带写空文件(相当于读到内存)
ibm01:/home/oracle$/tmp/sqluldr2_aix64_9208.bin a/a query="select * from t" file=/tmp/in.txt
       0 rows exported at 2010-03-01 19:37:57, size 0 MB.
1000000 rows exported at 2010-03-01 19:37:59, size 12 MB.
         output file /tmp/in.txt closed at 1000000 rows, size 16 MB.
读写物理文件


单纯看归并过程:
我那个树归并也比ORACLE慢,他可能是hash归并。我要是用hash可能达到他的速度,但hash表占用内存比较大。
树的逻辑比较简单,也比较通用。
你那个程序我不太懂,好像把3个列组装成一个key,也是一种hash法?冲突如何处理,null怎样解决?(替newkid问)。
不是3列,而是4个列的组合,就是group by 的组合,不算hash,但可以保证唯一,null用127代替
我从文档看到stl标准模板库的map是红黑树

[ 本帖最后由 〇〇 于 2010-3-1 19:45 编辑 ]

使用道具 举报

回复
论坛徽章:
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
486#
发表于 2010-3-1 19:40 | 只看该作者
原帖由 yulihua49 于 2010-3-1 14:25 发表

你没有包括数据库读写。如果原始数据在数据库,你光是把它们读出来就已经比group  by cube慢了。

--ibm01:/home/oracle$/tmp/sqluldr2_aix64_9208.bin a/a query="select * from t" file=/dev/null
       0 rows exported at 2010-02-26 17:08:55, size 0 MB.
1000000 rows exported at 2010-02-26 17:08:57, size 12 MB.
         output file /dev/null closed at 1000000 rows, size 16 MB.
连读带写空文件
ibm01:/home/oracle$/tmp/sqluldr2_aix64_9208.bin pjpdata/pjpdata query="select * from t" file=/tmp/in.txt
       0 rows exported at 2010-03-01 19:37:57, size 0 MB.
1000000 rows exported at 2010-03-01 19:37:59, size 12 MB.
         output file /tmp/in.txt closed at 1000000 rows, size 16 MB.
读写物理文件

单纯看归并过程:
我那个树归并也比ORACLE慢,他可能是hash归并。我要是用hash可能达到他的速度,但hash表占用内存比较大。
树的逻辑比较简单,也比较通用。
你那个程序我不太懂,好像把3个列组装成一个key,也是一种hash法?冲突如何处理,null怎样解决?(替newkid问)。

使用道具 举报

回复
论坛徽章:
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
487#
发表于 2010-3-1 23:35 | 只看该作者
"好吧,给你一个不用DAU的OCI程序的例子,你就知道为什么要用结构映射了:

比起48页478楼的例子,它只能加载我们前边说的tjrb表,还不能处理重码问题。
加载这个表(从空表),DAU的时间是1.1秒,这个程序是2.4秒,区别在于它没有用结构,每次从文件读入的行,每列的位置不固定,因此不能一次绑定,多次使用。
它也是保留游标的,但每次绑定变量,效率。。。。。。。"

你为什么要一行一行绑定呢?我虽然不熟悉但也知道OCI有个BULK BIND,比如这个:
http://forums.oracle.com/forums/ ... 165968&#2165968

你完全可以一次把几千行数据进行绑定,然后只要执行一次INSERT.

如果不处理事务,结构就没什么意义,结构的意义在于按成员的名字访问数据。

你这个DIY的数据加载器,再高明也只是敝帚自珍,因为有其他的更强大的工具,我是绝不会再自作聪明去DIY一个。

“处理业务逻辑,使用列名是不可避免的,但存取数据还要列举列名是多么痛苦的一件事,这个程序已经列举3遍了,还不包括对结构的映射。”
那就交给存储过程去做好了,存储过程里列举列名轻而易举,你一看程序就知道在操作什么数据。

"hibernate,你不用,用的大有人在,火得很哦。包装简化了使用,即使损失些效率,也受欢迎。"
只要不是单表操作,那么你这个DAU就要求把SQL写出来,而且还要塞进去其他东西,而且还要把SQL分成几截再拼起来。
因此到最后程序员都用单表操作,因为会自动生成模板,这就和许多hibernate程序员的恶习一样。

使用道具 举报

回复
论坛徽章:
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
488#
 楼主| 发表于 2010-3-2 11:06 | 只看该作者
原帖由 newkid 于 2010-3-1 23:35 发表
"好吧,给你一个不用DAU的OCI程序的例子,你就知道为什么要用结构映射了:

比起48页478楼的例子,它只能加载我们前边说的tjrb表,还不能处理重码问题。
加载这个表(从空表),DAU的时间是1.1秒,这个程序是2.4秒,区别在于它没有用结构,每次从文件读入的行,每列的位置不固定,因此不能一次绑定,多次使用。
它也是保留游标的,但每次绑定变量,效率。。。。。。。"

你为什么要一行一行绑定呢?我虽然不熟悉但也知道OCI有个BULK BIND,比如这个:
http://forums.oracle.com/forums/thread.jspa?messageID=2165968?

你完全可以一次把几千行数据进行绑定,然后只要执行一次INSERT.

如果不处理事务,结构就没什么意义,结构的意义在于按成员的名字访问数据。

你这个DIY的数据加载器,再高明也只是敝帚自珍,因为有其他的更强大的工具,我是绝不会再自作聪明去DIY一个。

“处理业务逻辑,使用列名是不可避免的,但存取数据还要列举列名是多么痛苦的一件事,这个程序已经列举3遍了,还不包括对结构的映射。”
那就交给存储过程去做好了,存储过程里列举列名轻而易举,你一看程序就知道在操作什么数据。

"hibernate,你不用,用的大有人在,火得很哦。包装简化了使用,即使损失些效率,也受欢迎。"
只要不是单表操作,那么你这个DAU就要求把SQL写出来,而且还要塞进去其他东西,而且还要把SQL分成几截再拼起来。
因此到最后程序员都用单表操作,因为会自动生成模板,这就和许多hibernate程序员的恶习一样。

数组绑定可以做,但不知道如果其中个别行错了,系统如何告我,如何定位是哪些行错了?

不要把例子理解为特定的问题,它代表一大类操作。比如加载,可能不是直接加载,而是变换加载,变换规则恐怕系统解决不了的吧?我这个加载可能被改写成各种变换。
另外关于开销分析:那个直接的OCI:

time ./ldtj <TJ.txt
connect TIMEVAL=40319
prepare TIMEVAL=300
loadfile:7552 load TIMEVAL=2489977 //操作时间 微秒
loadfile:7552 commit TIMEVAL=82380

real    0m2.628s
user    0m1.132s
sys     0m0.312s

DAU:
time ./ldasc TJRB <TJ.txt

real    0m1.295s
user    0m0.272s
sys     0m0.072s

日志:
2 loadsth:4194 03/02 10:40'10 loadfile:rows=7552,upd=0,loss=0,TIMEVAL=1097442  //操作时间 微秒
5 loadsth:4194 03/02 10:40'10 loadfile:7552 commit TIMEVAL=184259,ret=0

可以看到,我的 user时间已经非常少了,这包括了包装开销和OCI程序自身的开销。程序优化余地不大了。
包装开销是远远小于直接操作的开销。

[ 本帖最后由 yulihua49 于 2010-3-2 11:34 编辑 ]

使用道具 举报

回复
论坛徽章:
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
489#
 楼主| 发表于 2010-3-2 14:54 | 只看该作者

回复 #496 newkid 的帖子

那就交给存储过程去做好了,存储过程里列举列名轻而易举,你一看程序就知道在操作什么数据。

处理业务时知道结构就足够了,存取时没必要点名,对着百十来个列名,一看就头大。

你这个DIY的数据加载器,再高明也只是敝帚自珍,因为有其他的更强大的工具,我是绝不会再自作聪明去DIY一个。

再说一遍,那只是个测试例,告诉你处理问题的方法。你不要目光那么局限,它可以扩充成无数应用。
通用加载卸载在我们系统里有一堆,不是这一个,但都是这个派生的。系统程序怎么也完不成千变万化的用户需求。

本来也没让你用,我们自己用的。

因此到最后程序员都用单表操作,因为会自动生成模板,这就和许多hibernate程序员的恶习一样。
有这种可能,虽然DAU可以处理复合语句,也可以调用存储过程,但单表是最简单的,对于懒的程序员,有可能单表化。hibernate也支持关联查询,看怎么用了。
好在DAU的单表操作效率还比较高,多数情况满足要求。还有,即使不用DAU,那些懒程序员们也多用单表操作,还不绑定变量。(我是指OCI程序员,PRO*C好一些,能自动绑定)。这个也不能完全怪DAU。

这个网站真有不少求高级SQL的贴,但对于庞大的程序员队伍只是少数。更多的是遇到难题,过程语言解决了,数据存取方面并不下太大功夫。

“如果不处理事务,结构就没什么意义,结构的意义在于按成员的名字访问数据。”
请问,没有结构,百十来个变量放哪?我那个OCIlib的例子你看了吗?那个帖子看了吗?怎么老是把已经回答的问题又问?
不就是因为没有结构导致程序缓慢,开销大吗?如果成组绑定就要动用结构数组。
费那么大劲给你写了个不用结构的程序(粘了那么多列名,我容易吗?),就是告诉你没有结构很糟糕,你楞没看懂。再仔细看看48页490楼的程序及说明。
那个程序能改成别的吗?90%的代码要改,我重写得了。
有没有意义你说了不算,你又不写C程序。

DAU很容易改啊,比如我们有数十个表要在节点间传送,所有这些表都安排了传送标志和时间戳(同名同类型)。
根据传送标志卸载并重新标记传送标志。加载时如果遇到重码,以时间戳新的为准。这个简单逻辑你用系统方法给我实现一个。
这用DAU实现很容易。一般都是定时卸载,按需要分发到其他节点。

还有往一些大表添加数据并正确处理重码,sqlldr+merge,太累,弄多少临时表啊,我那百十来行的程序轻易解决了。

[ 本帖最后由 yulihua49 于 2010-3-2 16:09 编辑 ]

使用道具 举报

回复
论坛徽章:
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
490#
发表于 2010-3-2 23:56 | 只看该作者
"处理业务时知道结构就足够了,存取时没必要点名,对着百十来个列名,一看就头大。"

我们的"处理业务"做法是不一样的。你们C程序员的思路:读取数据,处理,写回去;
PLSQL程序员的思路:一个SQL搞定。
比如生成一条交易记录我会这么写:
INSERT INTO TRANSACTIONS (TXN_ID,TXN_TIME,CUSTOMER_ID,ITEM_ID,PRICE,QTY,AMOUNT)
SELECT SEQ_TXN.NEXTVAL,SYSDATE,P_CUSTOMER_ID,P_ITEM_ID,PRICE,PRICE*P_QTY - DISCOUNT)
  FROM ITEMS
WHERE ITEM_ID = P_ITEM_ID
这里面包含了读,写,和所有的处理。你清楚地看到它们的关系。


"请问,没有结构,百十来个变量放哪?我那个OCIlib的例子你看了吗?那个帖子看了吗?怎么老是把已经回答的问题又问?"
我看不出为什么不能用一个二维数组来存放数据?你490楼写了一堆OCI_BindString然后说速度不快,我说可以用数组绑定,不必一行一行地逐个绑定。
你要我写出来咱可没办法,再给你GOOGLE个例子:
http://www.allenhayden.com/cgi/getdoc.pl?file=ociperf.pdf

第9页:
Below is an example of using the array interface in OCI:
/* Insert array of 10 employees */
Lda_def lda;
ubl hda[256];
Cda_def cda; /* cursor data area */
char names[10][NLEN];
char emp_nos[10];
text *sql_stmt = "INSERT INTO \
emp(ename, empno) VALUES (:N, :E)";
...
orlon(&lda, hda, "scott/tiger",...);
oopen(&cda, &lda,...);
oparse(&cda, sql_stmt,...);
obndra(&cda, ":N",-1,names,...);
obndra(&cda, ":E",-1,emp_nos,...);
/* fill arrays, then execute */
oexn(&cda, ARRSIZE, 0);
oclose(&cda);
ologof(&lda);

你可以写一个通用的,先解析数据结构,再循环调用obndra. 当然没那么容易,我只是说可以不用结构。


"根据传送标志卸载并重新标记传送标志。加载时如果遇到重码,以时间戳新的为准。这个简单逻辑你用系统方法给我实现一个。
这用DAU实现很容易。一般都是定时卸载,按需要分发到其他节点。"
我轻而易举用MATERIALIZED VIEW就给你实现了,一行代码也不写。

既然说到时间戳,我且来考考你,这就叫做抬杠不忘布道。你是如何判断增量修改的?

一般人做法:
1.本次刷新时间=系统当前时间
2.SELECT * FROM 源表 WHERE 时间戳>=上次刷新时间
3.把步骤2结果写入目标

你也是这么做的吗?这里面的漏洞看出来没有?

使用道具 举报

回复

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

本版积分规则 发表回复

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