ocilib提供了以下几个执行sql语句的函数
OCI_ExecuteStmt/OCI_ExecuteStmtFmt 使用没有绑定变量的语句
OCI_Execute 使用有绑定变量的语句
OCI_Immediate/OCI_ImmediateFmt 使非绑定,可返回单行的语句,可以马上输出select值到参数变量中
表结构
create table oci_parse(rid number(10),rtm date default sysdate,rname varchar2(30));
RNAME | seconds | COUNT(*) |
OCI_Prepare out of loop | 31 | 100000 |
ImmediateFmt static sql | 123 | 100000 |
OCI_Prepare in loop | 35 | 100000 |
ExecuteStmtFmt static sql | 130 | 100000 |
Immediate static sql | 34 | 100000 |
ExecuteStmt static sql | 29 | 100000 |
首先先看结果,执行类似于
insert into oci_parse (rid, rname) values ( 99, 'ExecuteStmt static sql')
语句,每次插入10W条记录。
SELECT t.rname,(max(t.rtm)-min(t.rtm) )*86400 ,count(*) FROM oci_parse t group by t.rname;
结论:
1、可以看得出带*Fmt函数执行的效率最低,不带*Fmt的函数执行效率都差不多。
查看
SELECT t.SQL_TEXT,t.PARSE_CALLS,t.LOADS,t.EXECUTIONS FROM V_$SQLAREA t where t.SQL_TEXT like '%oci_parse%';
能发现很多*Fmt执行的语句,所以可以判断每条sql语句oracle都进行了解析;而不含*Fmt的语句,只有一条。
对比含*Fmt执行时间(平均126.5s)和不含*Fmt的执行时间(平均32.25s),执行含*Fmt语句要比执行不含*Fmt的语句要多花费3倍的时间。
2、对于OCI_Prepare 循环内绑定语句和循环外绑定语句,循环外绑定语句效率要稍高(31对35),但差别并不是很大。
3、对于静态的sql语句,OCI_Immediate和OCI_ExecuteStmt差别并不大(29对34,另外一次测试是33对32)。
就效率而言,从高到低
ExecuteStmt (static sql) = Immediate(static sql) > OCI_Prepare(out of loop) > OCI_Prepare (in loop) >> ImmediateFmt = ExecuteStmtFmt
int main(){
OCI_Connection *cn;
OCI_Statement *st;
OCI_Resultset *rs;
char dbs [] ="10.8.50.192/dev";
char usr []= "duser";
char pwd []="pwd123456" ; int rid;
char rname[30];
printf("rname [%s] size =%d\n",rname,sizeof(rname));
int i; if (!OCI_Initialize(err_handler, NULL, OCI_ENV_DEFAULT))
return EXIT_FAILURE;
OCI_EnableWarnings(TRUE); cn = OCI_ConnectionCreate(dbs, usr, pwd, OCI_SESSION_DEFAULT);
st = OCI_StatementCreate(cn); if( !OCI_Prepare(st, "insert into oci_parse "
"(rid, rname)"
"values ( :rid, :rname)"
)){
return -1;
};
OCI_BindInt(st, OTEXT(":rid"), &rid);
OCI_BindString(st, OTEXT(":rname"), (otext*) rname, sizeof(rname));
for(i=0;i<100000;i++){ rid = 99;
strcpy(rname,"OCI_Prepare out of loop"); if(!OCI_Execute(st)){
printf("line %d",__LINE__);
return -1;
}
}
OCI_Commit(cn); for(i=0;i<100000;i++){
if( !OCI_Prepare(st, "insert into oci_parse "
"(rid, rname)"
"values ( :rid, :rname)"
)){
printf("line %d",__LINE__);
return -1;
};
OCI_BindInt(st, OTEXT(":rid"), &rid);
OCI_BindString(st, OTEXT(":rname"), (otext*)rname, sizeof(rname));
rid = 99;
strcpy(rname,"OCI_Prepare in loop");
if(!OCI_Execute(st)){
printf("line %d",__LINE__);
return -1;
}
} OCI_Commit(cn); for(i=0;i<100000;i++){
if( !OCI_ExecuteStmt(st, "insert into oci_parse (rid, rname) values ( 99, 'ExecuteStmt static sql') ")){
printf("line %d",__LINE__);
return -1;
}
}
OCI_Commit(cn); for(i=0;i<100000;i++){
if( !OCI_ExecuteStmtFmt(st, "insert into oci_parse (rid, rname) values ( %i, 'ExecuteStmtFmt static sql') ",i)){
printf("line %d",__LINE__);
return -1;
}
}
OCI_Commit(cn);
for(i=0;i<100000;i++){
if(!OCI_Immediate(cn, "insert into oci_parse (rid, rname) values ( 99, 'Immediate static sql') ")){
printf("line %d",__LINE__);
return -1;
}
}
OCI_Commit(cn); for(i=0;i<100000;i++){
if(!OCI_ImmediateFmt(cn, "insert into oci_parse (rid, rname) values ( %i, 'ImmediateFmt static sql') ",i+100000)){
printf("line %d",__LINE__);
return -1;
}
}
OCI_Commit(cn); OCI_Cleanup();
return 0;
}
pro*c插入10W记录耗时31秒,对比OIClib而言,性能相等。但OIClib多了很多功能,这是pro*c无法提供的。
int main()
{
EXEC SQL BEGIN DECLARE SECTION;
char *sid = "duser/pwd123456@10.8.50.192/dev";
char rname[16];
int rid;
EXEC SQL END DECLARE SECTION;
int i;
EXEC SQL CONNECT :sid;
printf("%s",sqlca.sqlerrm.sqlerrmc);
if(sqlca.sqlcode == 0)
printf("CONNECT OK\n");
else
printf("CONNECT ERROR, sqlcode = %d\n", sqlca.sqlcode); for(i=0;i<100000;i++){
rid=89;
strcpy(rname,"pro*c");
EXEC SQL
insert into oci_parse (rid, rname) values ( :rid, :rname) ;
}
EXEC SQL COMMIT work release;
return 0;
}