oracle 插入 基准测试,oracle proc 插入操作性能优化实践
場景:
student 表中 10萬條數(shù)據(jù)。
從 student 表中取出所有數(shù)據(jù),插入到 student_his 表中
優(yōu)化方法:
1.批量插入(效果明顯)
2.批量查詢(效果不明顯)
3.批量提交(效果不明顯)
4.預(yù)編譯 sql 語句(效果不明顯)
效果:
10萬條數(shù)據(jù),普通方法 27 秒,優(yōu)化后 8 秒
測試步驟:
1.創(chuàng)建數(shù)據(jù)庫表
create tablestudent
(
student_idinteger,
student_namevarchar2(20),
salaryfloat(126)
);create unique index index_student_id onstudent(student_id);insert into student (student_id, student_name, salary) values (1, ‘test‘, 2);create tablestudent_his
(
student_idinteger,
student_namevarchar2(20),
salaryfloat(126)
);create unique index index_student_his_id on student_his(student_id);
2.準(zhǔn)備數(shù)據(jù):
insert.pc 插入 10萬條數(shù)據(jù)
vim insert.pc
#include #include
/*插入條數(shù)*/
#define COUNTNUM 100000
/*數(shù)組大小*/
#define RECORDNUM 1000EXEC SQL INCLUDE SQLCA;voidsqlerror();
typedefstructRecord
{intstudent_id;char student_name[20];floatsalary;
}Record;intmain()
{
EXEC SQL BEGIN DECLARE SECTION;char username[20];char password[20];char db_name[20];intstudent_id;char student_name[15];floatsalary;
Record records[RECORDNUM];
EXEC SQL END DECLARE SECTION;
printf("size:%d\n",sizeof(records));int j = 0;int i = 0;int count = 1;/*出錯處理*/EXEC SQL WHENEVER SQLERROR DO sqlerror();
EXEC SQL WHENEVER NOT FOUND GOTO notfound;/*鏈接數(shù)據(jù)庫*/strcpy(username,"ngbs");
strcpy(password,"ngbs");
strcpy(db_name,"ngbs");
EXEC SQL CONNECT :username IDENTIFIED BY :password USING :db_name;/*獲取當(dāng)前最大id號,防止插入重復(fù)*/EXEC SQL SELECT max(student_id) INTO :student_id FROM student;
printf("max student_id:%d\n", student_id);for(j=0; j
{
memset (records,0, sizeof(records));for(i=0; i
{
records[i].student_id= student_id+count;
sprintf(records[i].student_name,"%s%d", "stu", student_id+i);
records[i].salary= student_id*i+0.5;//printf("student_id=%d, student_name=%s, salary=%f\n", records[i].student_id, records[i].student_name, records[i].salary);
count++;
}/*使用數(shù)組方式一次插入多條紀(jì)錄*/EXEC SQL INSERT INTO student(student_id,student_name,salary) values (:records);
}
notfound:/*提交*/EXEC SQL COMMIT WORK RELEASE;
printf("ok\n");return 0;
}voidsqlerror()
{/*出錯回滾*/EXEC SQL WHENEVER SQLERROR CONTINUE;
printf("ORACLE error detected:\n");
printf("%s\n", sqlca.sqlerrm.sqlerrmc);
EXEC SQL ROLLBACK;
}
編譯運(yùn)行腳本:
vim runin.sh
proc insert.pccc -g -o insert insert.c -L$ORACLE_HOME/lib -L$ORACLE_HOME/rdbms/lib -L/usr/lib64 -lclntsh -lm -lctime ./insert
3.對比兩種處理方法的快慢
common.pc 使用一般游標(biāo)方式
#include #include#includeEXEC SQL INCLUDE SQLCA;voidsqlerror();
typedefstructRecord
{intstudent_id;char student_name[20];floatsalary;
}Record;intmain()
{
EXEC SQL BEGIN DECLARE SECTION;char username[20];char password[20];char db_name[20];intstudent_id;char student_name[15];floatsalary;char strsql[256];
Record records;
EXEC SQL END DECLARE SECTION;
printf("records size:%d\n",sizeof(records));
memset(strsql,0, sizeof(strsql));/*出錯處理*/EXEC SQL WHENEVER SQLERROR DO sqlerror();
EXEC SQL WHENEVER NOT FOUND GOTO notfound;/*鏈接數(shù)據(jù)庫*/strcpy(username,"ngbs");
strcpy(password,"ngbs");
strcpy(db_name,"ngbs");
EXEC SQL CONNECT :username IDENTIFIED BY :password USING :db_name;/*清空*/EXEC SQL TRUNCATE TABLE student_his;/*打開游標(biāo)*/sprintf(strsql,"select * from student");
printf("strsql:%s\n", strsql);
EXEC SQL PREPARE sql_stmt FROM :strsql;if(sqlca.sqlcode)
{
printf("sql_stmt error[%d]", sqlca.sqlcode);returnsqlca.sqlcode;
}
EXEC SQL DECLARE sel_cursor cursorforsql_stmt;if(sqlca.sqlcode)
{
printf("cursor error[%d]", sqlca.sqlcode);returnsqlca.sqlcode;
}
EXEC SQL OPEN sel_cursor;if(sqlca.sqlcode)
{
printf("open error[%d]", sqlca.sqlcode);returnsqlca.sqlcode;
}int flag = 1;while(flag)
{/*取出數(shù)據(jù) student*/EXEC SQL FETCH sel_cursor INTO :records;/*插入 student_his*/EXEC SQL INSERT INTO student_his values(:records);
}
notfound:/*提交*/EXEC SQL COMMIT WORK RELEASE;
printf("ok\n");return 0;
}voidsqlerror()
{/*出錯回滾*/EXEC SQL WHENEVER SQLERROR CONTINUE;
printf("ORACLE error detected:\n");
printf("%s\n", sqlca.sqlerrm.sqlerrmc);
EXEC SQL ROLLBACK;
exit(1);
}
編譯運(yùn)行腳本:
vim runco.sh
proc common.pccc -g -o common common.c -L$ORACLE_HOME/lib -L$ORACLE_HOME/rdbms/lib -L/usr/lib64 -lclntsh -lm -lctime ./common
fast.pc 使用游標(biāo)+結(jié)構(gòu)體數(shù)組方式
#include #include#include
/*數(shù)組大小*/
#define RECORDNUM 1000EXEC SQL INCLUDE SQLCA;voidsqlerror();
typedefstructRecord
{intstudent_id;char student_name[20];floatsalary;
}Record;intmain()
{
EXEC SQL BEGIN DECLARE SECTION;char username[20];char password[20];char db_name[20];intstudent_id;char student_name[15];floatsalary;char strsql[256];
Record records[RECORDNUM];
EXEC SQL END DECLARE SECTION;
printf("records size:%d\n",sizeof(records));
memset(strsql,0, sizeof(strsql));
memset(records,0, sizeof(records));/*出錯處理*/EXEC SQL WHENEVER SQLERROR DO sqlerror();
EXEC SQL WHENEVER NOT FOUND GOTO notfound;
EXEC ORACLE OPTION (HOLD_CURSOR=YES);/*鏈接數(shù)據(jù)庫*/strcpy(username,"ngbs");
strcpy(password,"ngbs");
strcpy(db_name,"ngbs");
EXEC SQL CONNECT :username IDENTIFIED BY :password USING :db_name;/*清空*/EXEC SQL TRUNCATE TABLE student_his;/*打開游標(biāo)*/sprintf(strsql,"select * from student");
printf("strsql:%s\n", strsql);
EXEC SQL PREPARE sql_stmt FROM :strsql;if(sqlca.sqlcode)
{
printf("sql_stmt error[%d]", sqlca.sqlcode);returnsqlca.sqlcode;
}
EXEC SQL DECLARE sel_cursor cursorforsql_stmt;if(sqlca.sqlcode)
{
printf("cursor error[%d]", sqlca.sqlcode);returnsqlca.sqlcode;
}
EXEC SQL OPEN sel_cursor;if(sqlca.sqlcode)
{
printf("open error[%d]", sqlca.sqlcode);returnsqlca.sqlcode;
}int flag = 1;while(flag)
{
memset(records,0, sizeof(records));/*一次取出多條數(shù)據(jù)*/EXEC SQL FETCH sel_cursor INTO :records;if(sqlca.sqlcode)
{if(sqlca.sqlcode == 100)
{
printf("NOT FOUND DATA[%d]", sqlca.sqlcode);if (sqlca.sqlerrd[2] >RECORDNUM)
{
printf("最后條數(shù):%d\n", sqlca.sqlerrd[2] -RECORDNUM);
flag= 0;
}else{/*沒有記錄*/
break;
}
}else{
printf("fetch error[%d]", sqlca.sqlcode);break;
}
}/*一次插入多條數(shù)據(jù)*/
EXEC SQL INSERT INTO student_his values(:records);
EXEC SQL COMMIT;
}
notfound:/*提交*/EXEC SQL COMMIT WORK RELEASE;
printf("ok\n");return 0;
}voidsqlerror()
{/*出錯回滾*/EXEC SQL WHENEVER SQLERROR CONTINUE;
printf("ORACLE error detected:\n");
printf("%s\n", sqlca.sqlerrm.sqlerrmc);
EXEC SQL ROLLBACK;
exit(0);
}
編譯運(yùn)行腳本:
vim runfa.sh
proc fast.pccc -g -o fast fast.c -L$ORACLE_HOME/lib -L$ORACLE_HOME/rdbms/lib -L/usr/lib64 -lclntsh -lm -lctime ./fast
說明:
fast.pc 中調(diào)用 memset() 清空數(shù)組的操作,這個操作在10萬次插入過程中會增加2-3秒的時間。
經(jīng)過測試,數(shù)組大小 RECORDNUM 設(shè)置為 1000 左右效率比較高,沒有進(jìn)行更細(xì)致范圍的測試。
原文:https://www.cnblogs.com/etangyushan/p/12575736.html
總結(jié)
以上是生活随笔為你收集整理的oracle 插入 基准测试,oracle proc 插入操作性能优化实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle不加IP无法登录,Oracl
- 下一篇: tcl c语言笔试题,TCL技术类笔试题