楼主: 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
221#
发表于 2009-2-12 11:00 | 只看该作者
我在翻番数据的时候已经改日期了,我没那么傻啦。

'TJRB'是一个DIRECTORY, 就是操作系统路径的映射。
你先用DBA 创建 CREATE DIRECTORY TJRB .... 然后GRANT给你的用户。
这个路径必须是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
222#
 楼主| 发表于 2009-2-12 11:41 | 只看该作者
原帖由 newkid 于 2009-2-12 11:00 发表
我在翻番数据的时候已经改日期了,我没那么傻啦。

'TJRB'是一个DIRECTORY, 就是操作系统路径的映射。
你先用DBA 创建 CREATE DIRECTORY TJRB .... 然后GRANT给你的用户。
这个路径必须是ORACLE用户有读取权限的。

多谢,成功了。
time ora <ldtj.sql

SQL*Plus: Release 10.2.0.3.0 - Production on Thu Feb 12 11:37:55 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  
PL/SQL procedure successfully completed.

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

real    0m2.344s
user    0m0.028s
sys     0m0.012s

用sqlldr的:
time ../sql/ldtj.sh

SQL*Loader: Release 10.2.0.3.0 - Production on Thu Feb 12 11:40:20 2009

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

Commit point reached - logical record count 717
Commit point reached - logical record count 1434
Commit point reached - logical record count 2151
Commit point reached - logical record count 2868
Commit point reached - logical record count 3585
Commit point reached - logical record count 4302
Commit point reached - logical record count 5019
Commit point reached - logical record count 5736
Commit point reached - logical record count 6453
Commit point reached - logical record count 7170
Commit point reached - logical record count 7552

real    0m1.131s
user    0m0.396s
sys     0m0.028s

用DAU的:
time ./ldasc <TJ.txt

real    0m1.320s
user    0m0.308s
sys     0m0.096s

我这个程序的功力是85%,你过程的功力是48%,还那么复杂。
DAU的日志:
5 ./loadsth:21373 02/12 11:42'09 tabname=tjrb
5 ./loadsth:21373 02/12 11:42'09 ___SQL_OpenDatabase__: Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options
5 ./loadsth:21373 02/12 11:42'09 DB=TICKET
5 ./loadsth:21373 02/12 11:42'09 loadfile:entry
5 ./loadsth:21373 02/12 11:42'09 mkpk:tjdate|unit|tabname|flg|
5 ./loadsth:21373 02/12 11:42'09 bind_ins:sth=0,stmt=INSERT INTO TICKET.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 (to_date(:1,'YYYY-MM-DD'), :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)
2 ./loadsth:21373 02/12 11:42'10 loadfile:rows=7552,upd=0,loss=0
2 ./loadsth:21373 02/12 11:42'10 loadasc:load 7552 rec's time=1,buf=2006.01.31


现在回过头来再研究怪异问题。sqlldr的 +append的语法是怎样写的?
FORALL的异常处理比较罗嗦我就不做了。请告诉我忽略错误的办法。

[ 本帖最后由 yulihua49 于 2009-2-12 14: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
223#
发表于 2009-2-13 00:49 | 只看该作者
我这个程序的功力是85%,你过程的功力是48%,还那么复杂。

现在回过头来再研究怪异问题。sqlldr的 +append的语法是怎样写的?
FORALL的异常处理比较罗嗦我就不做了。请告诉我忽略错误的办法。

我就知道你要这么说,要不我怎么迟迟不出手呢?你要说高射炮打蚊子不如苍蝇拍那我也没办法。

sqlldr的直接路径加载参数:DIRECT=TRUE

忽略错误的办法:用MERGE, 或 INSERT INTO ... SELECT ... FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM .... WHERE 主键=...)

使用道具 举报

回复
论坛徽章:
7
2010数据库技术大会纪念徽章
日期:2010-05-13 09:34:22
224#
发表于 2009-2-13 08:21 | 只看该作者
原帖由 newkid 于 2009-2-13 00:49 发表

我就知道你要这么说,要不我怎么迟迟不出手呢?你要说高射炮打蚊子不如苍蝇拍那我也没办法。
你不赞成这个说法么?打蚊子就要用苍蝇拍呀,嘻嘻


sqlldr的直接路径加载参数:DIRECT=TRUE

忽略错误的办法:用MERGE, 或 INSERT INTO ... SELECT ... FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM .... WHERE 主键=...)

使用道具 举报

回复
论坛徽章:
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
225#
发表于 2009-2-13 10:01 | 只看该作者
就是苍蝇拍我也喜欢O记老字号的!

使用道具 举报

回复
论坛徽章:
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
226#
 楼主| 发表于 2009-2-17 14:05 | 只看该作者
原帖由 newkid 于 2009-2-13 00:49 发表

我就知道你要这么说,要不我怎么迟迟不出手呢?你要说高射炮打蚊子不如苍蝇拍那我也没办法。

sqlldr的直接路径加载参数:DIRECT=TRUE

忽略错误的办法:用MERGE, 或 INSERT INTO ... SELECT ... FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM .... WHERE 主键=...)

谢。
那么,至少你也应该承认,包装器速度不慢。今后可以不在速度上叫板了。
怪异问题,追踪到sqlora程序,这是个开源程序。到这么一句:
else if ( _is_prepared(stp) ) {
    dbp->status = OCIStmtExecute( dbp->svchp,
                                  stp->stmthp,
                                  dbp->errhp,
                                  (ub4) iterations,
                                  (ub4) 0,
                                  (OCISnapshot *) 0,
                                  (OCISnapshot *) 0,
                                  dbp->exec_flags
                                  );
删掉这句话,立刻就快了,0.几秒,可是什么也不干了。就是说,问题跑到OCI里了,我有点没辙了。不知别人用OCI出现此问题么?
目前只好提供假修改函数临时解决一下。

做了dumy_update,程序(一个DAO函数):
static int dumy_update(DAU *DP,char *stmt)
{
int ret;

        if(DP->upd_sth<0) {
                char *p=stmt;
                p+=sprintf(p,"UPDATE ");
                if(*DP->SQL_Connect->DBOWN) p+=sprintf(p,"%s.",DP->SQL_Connect->DBOWN);
                p+=sprintf(p,"%s set %s=:%s ",
                        DP->srm.tabname,
                        DP->srm.tp[0].name,
                        DP->srm.tp[0].name);
                p=DAU_mk_where(DP,DP->srm.pks,p);
ShowLog(5,"dumy_update:stmt=%s",stmt);
        }
        return DAU_update(DP,stmt);
}


结果如下:
:~/test> time ./ldasc -P/dev/null <TJ.txt

real    0m5.440s
user    0m1.056s
sys     0m0.500s
时间跟真update差不多,看来,改一个字段与改54个字段没什么区别( 5.44秒与 5.65秒之区别)。以后还真别为了少操作几个字段大动干戈,使用子模板什么的。
日志;
5 ./loadsth:29995 02/17 15:39'13 bind_ins:sth=0,stmt=INSERT INTO TICKET.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 (to_date(:1,'YYYY-MM-DD'), :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)
5 ./loadsth:29995 02/17 15:39'13 dumy_update:stmt=UPDATE TICKET.tjrb set tjdate=:tjdate WHERE tjdate=:tjdate AND unit=:unit
AND tabname=:tabname AND flg=:flg

5 ./loadsth:29995 02/17 15:39'13 bind_update:bind=5,sth=1,stmt=UPDATE TICKET.tjrb set tjdate=to_date(:1,'YYYY-MM-DD')
WHERE tjdate=to_date(:2,'YYYY-MM-DD') AND unit=:3 AND tabname=:4 AND flg=:5,
2 ./loadsth:29995 02/17 15:39'19 loadfile:rows=0,upd=0,loss=7552
2 ./loadsth:29995 02/17 15:39'19 loadasc:load 0 rec's time=6,buf=2006.01.31|55|A7|102|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|

可以看到,包装器为你做了一点工作,你写日期的格式字段和where的主键条件生成都省事了。

刚才网上搜罗一下OCI程序,看到那么多人在痛苦的OCI深渊里挣扎,那么多痛苦的问题,其实我这个包装器都可以解决,真是感到没办法救他们。
虽然用OCI写程序的少之又少,但凡用这东西都有难言之隐,多数是有性能问题或多功能的通用软件。看到许多代码也都是包装器性质,为什么不推出通用数据库访问框架呢?

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

使用道具 举报

回复
论坛徽章:
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
227#
 楼主| 发表于 2009-2-17 16:14 | 只看该作者
原帖由 newkid 于 2009-2-11 23:51 发表
至于你说的“打开了插入游标,每次插入彻底排除了语句分析和执行计划……”云云,这在PLSQL是完全自动实现的,我根步不用操心。

没有看到自动游标的处理,因为如果自动保持游标,就需要一个关闭的过程,什么时候关闭呢?所以我认为,至多是保持了一个语句。
我试过,保持语句和保持游标性能还是差不少的(1.5-3倍)。

使用道具 举报

回复
论坛徽章:
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
228#
发表于 2009-2-18 01:34 | 只看该作者
那么,至少你也应该承认,包装器速度不慢。今后可以不在速度上叫板了。


对付特定问题,你的C程序在速度上可以超过PLSQL, 无限接近SQLLDR, 这个我一点也不怀疑。
PLSQL的强项在于它和SQL的亲和力,它的处理事务的能力要大量借助SQL的威力。比如一个排序算法,你用PLSQL来实现,那和C是没得比的,但是没有一个程序员会这么做,大家都是在SQL中简单的ORDER BY就完成了。在一个在线事务中,用户输入的数据在整个事务数据中往往只占一小部分(这个和数据加载完全不同),有时候只是打一个勾,点一个按钮就完成了所有的操作,可是后台却触发很多计算:取账户余额,取账户历史,取系统参数,……里面有大量和数据库打交道的动作。用你的包装器,程序员的思路局限于单表操作、单记录循环操作(而不是集合操作),而用PLSQL编程则会大量使用SQL进行运算,让数据库直接给出运算结果,客户端只需要一个调用,省却了和数据库的许多来回交互。因此密集型高并发的事务处理,是PLSQL大显身手的地方。

没有看到自动游标的处理,因为如果自动保持游标,就需要一个关闭的过程,什么时候关闭呢?所以我认为,至多是保持了一个语句。

这是因为你不了解PLSQL. PLSQL和其他编程语言不同的地方就在于它的隐性游标。你在程序中看不到什么打开、关闭游标的动作,直接写SQL就行了,其他的事情PLSQL引擎都替你做掉了。同一个SESSION中的隐性游标会被自动CACHE住,这样第二次调用时,PLSQL根本不会再打开新游标。(现在的架构都是使用连接池的,因此SESSION会被很多客户共享,因而游标也被共享)
而这一切都是透明的,程序员根本不用操心。
再比如绑定变量,PLSQL中要写一个非绑定变量的SQL还很费劲呢!一切都是自动绑定的。
TOM的EFFECTIVE ORACLE BY DESIGN专门有一节讲述PLSQL和其他语言相比的优势,可惜这个没有电子版,要不然可以推荐你读一读。

使用道具 举报

回复
论坛徽章:
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
229#
 楼主| 发表于 2009-2-18 16:47 | 只看该作者
原帖由 newkid 于 2009-2-18 01:34 发表

这是因为你不了解PLSQL. PLSQL和其他编程语言不同的地方就在于它的隐性游标。你在程序中看不到什么打开、关闭游标的动作,直接写SQL就行了,其他的事情PLSQL引擎都替你做掉了。同一个SESSION中的隐性游标会被自动CACHE住,这样第二次调用时,PLSQL根本不会再打开新游标。(现在的架构都是使用连接池的,因此SESSION会被很多客户共享,因而游标也被共享)
而这一切都是透明的,程序员根本不用操心。
再比如绑定变量,PLSQL中要写一个非绑定变量的SQL还很费劲呢!一切都是自动绑定的。
TOM的EFFECTIVE ORACLE BY DESIGN专门有一节讲述PLSQL和其他语言相比的优势,可惜这个没有电子版,要不然可以推荐你读一读。

你的意思,OCI与PL/SQL是不同的?PLSQL有隐性游标,而OCI没有?

关于插入怪异问题,经实验,一个成功的update可以缩短时间,而失败的update不起作用。

关于order by和 group by的问题。
十几年前,我们试验,在内存用二叉树分组排序,比数据库快很多,所以当年一度要求不使用order和group,而用二叉树,因此框架提供二叉树和链表方法。
现在好多年不用了,也懒的做实验,就信你的吧。

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

使用道具 举报

回复
论坛徽章:
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
230#
发表于 2009-2-18 23:41 | 只看该作者
原帖由 yulihua49 于 2009-2-18 16:47 发表

你的意思,OCI与PL/SQL是不同的?PLSQL有隐性游标,而OCI没有?

关于插入怪异问题,经实验,一个成功的update可以缩短时间,而失败的update不起作用。

关于order by和 group by的问题。
十几年前,我们试验,在内存用二叉树分组排序,比数据库快很多,所以当年一度要求不使用order和group,而用二叉树,因此框架提供二叉树和链表方法。
现在好多年不用了,也懒的做实验,就信你的吧。


你让我怎么说呢?OCI只是个和数据库引擎打交道的接口,PLSQL的底层也是OCI.
而隐性游标是PLSQL提高的高一层的功能,它会利用OCI去自动打开游标、绑定、执行、FETCH、根据需要决定是否关闭。
PLSQL程序员只需要写SQL就行了,典型的如:
SELECT ...
  INTO 变量
  FROM ....

其他的根本不要操心。这就是一个隐性游标。
其他语言没有这功能,因此使用SQL没有那么方便,从而造成了程序员不喜欢甚至害怕使用SQL。

你可以说PLSQL也是一个包装器,但它和你的包装器截然相反:它鼓励使用SQL, 为使用SQL提供了很多便利。

如果你的排序比SQL快,那肯定不是ORACLE数据库,要不你就试试。我和你恰恰相反,有时候我的数据在内存中不在表中,我也宁愿写几行SQL进行排序而不愿自己做。

使用道具 举报

回复

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

本版积分规则 发表回复

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