SQLite3开启事务和关闭事务模式下,性能测试对比

前端之家收集整理的这篇文章主要介绍了SQLite3开启事务和关闭事务模式下,性能测试对比前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
@H_404_0@最近学习了下sqlite数据库基本知识,想了解下这款小巧的数据库性能到底怎样,于是写个性能测试程序,对 sqlite3 最新发布版(3.7.13)在Linux平台进行了测试。最后发现在开启事务模式和关闭事务模式(默认)下,性能测试结果相差近 1000 倍!

在测试的过程中,得出如下一些结论:

1、对于批量数据操作,建议采用事务模式,批量提交操作。

2、在提交事务之前,若程序发生异常,则所有插入、更新、删除等操作,都不会成功。

3、在操作数据库时,程序发生异常而中断操作,不会对现有的数据库造成任何破坏(sqlite3 的可靠性还不错!)。

一、测试环境
操作系统类型:linux-suse11 2.6.34.10-0.6-desktop,x86-32
操作系统内核:2.6.34.10-0.6-desktop
编译器版本 : gcc (SUSE Linux) 4.5.0 20100604 [gcc-4_5-branch revision 160292]
数据库版本 : sqlite 3.7.13
cpu 配置 :AMD Athlon(tm) II X2 240 Processor, 2812.890 MHZ, 1024 KB cache size,dual core
内存配置 :1017812 kB

二、编译方法
1、开启事务模式编译: gcc -Wall -lpthread -ldl testsqlite3.c sqlite3.c -o main -DTRANSACTION_ON;
2、关闭事务模式编译: gcc -Wall -lpthread -ldl testsqlite3.c sqlite3.c -o main;

三、测试结果:

测试结果单位:微秒(μs), 1秒=1000毫秒=1000000微秒

1、关闭事务模式(默认)

操作类型 CountsTotalTime(us)AverageTime(us)
插入 1000 31307617 31307.000000
查询 1000 944442 944.000000
更新1000 32264043 32264.000000
删除 1000 30638604 30638.000000

2、开启事务模式

操作类型 CountsTotalTime(us)AverageTime(us)
插入 1000 23326 23.000000
查询 1000 935739 935.000000
更新 1000 39197 39.000000
删除 1000 24394 24.000000

四、源代码

  1. /******************************************************************************
  2. CopyrightbyJavacode007,Allrightsreserved!
  3. Filename:testsqlite3.c
  4. Author:Javacode007
  5. Date:2012-8-11
  6. Version:1.0
  7. Description:sqlite3基本功能性能测试
  8. ******************************************************************************/
  9. #include"sqlite3.h"
  10. #include<stdlib.h>
  11. #include<stdio.h>
  12. #include<string.h>
  13. #include<sys/time.h>
  14. #include<time.h>
  15. #definePRINT_TRACE(fmt,args...)do{\
  16. fprintf(stderr,fmt"File:%s,Line:%04d\r\n",##args,__FILE__,__LINE__);\
  17. \
  18. }@H_404_149@while(0)
  19. #ifdefTRANSACTION_ON
  20. #defineSTART_TRANSACTION()sqlite3_exec(db,"begintransaction;",NULL,NULL)
  21. #defineEND_TRANSACTION()sqlite3_exec(db,"committransaction;",NULL)
  22. #else
  23. #defineSTART_TRANSACTION()
  24. #defineEND_TRANSACTION()
  25. #endif
  26. //性别枚举类型
  27. @H_404_149@typedef@H_404_149@enum
  28. {
  29. UNKNOWN,
  30. MALE,
  31. FEMALE,
  32. }SEX_E;
  33. //sql操作枚举类型
  34. @H_404_149@typedef@H_404_149@enum
  35. {
  36. INSERT,
  37. SELECT,
  38. UPDATE,
  39. DELETE
  40. }sql_OPTYPE;
  41. @H_404_149@typedef@H_404_149@structstEmployee
  42. {
  43. unsignedintid;
  44. unsignedintage;
  45. SEX_Esex;
  46. charregistertime[26];
  47. charcellphone[12];
  48. charemail[128];
  49. charresume[512];
  50. floatsalary;
  51. }Employee_S;
  52. //全局雇员ID
  53. @H_404_149@staticunsignedintg_employeeid;
  54. longdiff_timeval(@H_404_149@structtimevaltv1,@H_404_149@structtimevaltv2)
  55. {
  56. longtimecost=0;
  57. timecost=1000000*(tv2.tv_sec-tv1.tv_sec)+(tv2.tv_usec-tv1.tv_usec);
  58. @H_404_149@returntimecost;
  59. }
  60. @H_404_149@voidinit_employee(Employee_S*employee)
  61. {
  62. time_tttime;
  63. @H_404_149@if(NULL==employee)
  64. {
  65. PRINT_TRACE("Invalidparameter:NULLpointer!");
  66. @H_404_149@return;
  67. }
  68. memset(employee,@H_404_149@sizeof(*employee));
  69. g_employeeid++;
  70. employee->id=g_employeeid;
  71. employee->age=0;
  72. employee->sex=UNKNOWN;
  73. time(&ttime);
  74. sprintf(employee->registertime,"%s",ctime(&ttime));
  75. sprintf(employee->cellphone,"%0*d",@H_404_149@sizeof(employee->cellphone)-1,0);
  76. sprintf(employee->email,"persion_%06d@sun.org",g_employeeid);
  77. sprintf(employee->resume,"Resume:");
  78. employee->salary=12345.78;
  79. }
  80. @H_404_149@voidprint_employee(Employee_Semployee)
  81. {
  82. printf("id=%d,age=%d,sex=%d,regtime=%s",employee.id,employee.age,employee.sex,employee.registertime);
  83. printf("cellphone=%s,email=%s,resume=%s,salary=%6.2f\r\n",employee.cellphone,employee.email,employee.resume,employee.salary);
  84. }
  85. sqlite3*open_db(@H_404_149@constchar*dbname)
  86. {
  87. intret=-1;
  88. sqlite3*db=NULL;
  89. @H_404_149@if(NULL==dbname)
  90. {
  91. PRINT_TRACE("Invalidparameter:nulldatabasename!");
  92. @H_404_149@returnNULL;
  93. }
  94. ret=sqlite3_open(dbname,&db);
  95. @H_404_149@if(sqlITE_OK!=ret)
  96. {
  97. PRINT_TRACE("Opendatabase\"%s\"Failed:%s.",dbname,sqlite3_errmsg(db));
  98. sqlite3_close(db);
  99. @H_404_149@returnNULL;
  100. }
  101. @H_404_149@returndb;
  102. }
  103. intclose_db(sqlite3*db)
  104. {
  105. intret=-1;
  106. @H_404_149@if(NULL!=db)
  107. {
  108. ret=sqlite3_close(db);
  109. }
  110. @H_404_149@returnret;
  111. }
  112. intcreate_table(sqlite3*db,@H_404_149@constchar*tablename)
  113. {
  114. intret=-1;
  115. intcmdlen=0;
  116. char*errmsg;
  117. char*sqlfmt="CREATETABLE%s(idINTEGERPRIMARYKEY,ageINTEGER,sex"
  118. "INTEGER,registertimeVARCHAR(26),cellphoneVARCHAR(12),"
  119. "emailTEXT,resumeTEXT,salaryREAL);";
  120. char*sqlcmd=NULL;
  121. @H_404_149@if(NULL==db||NULL==tablename)
  122. {
  123. PRINT_TRACE("Invalidparameter:&db=%p,&tablename=%p.",db,tablename);
  124. @H_404_149@returnret;
  125. }
  126. //必须用strlen获取字符长度,不能用sizeof,sizeof获取的是指针长度,为4.
  127. cmdlen=strlen(sqlfmt)+strlen(tablename)+1;
  128. sqlcmd=(char*)malloc(cmdlen);
  129. @H_404_149@if(NULL==sqlcmd)
  130. {
  131. PRINT_TRACE("Notenoughmemoryforsqlcommand!");
  132. @H_404_149@returnret;
  133. }
  134. memset(sqlcmd,cmdlen);
  135. sprintf(sqlcmd,sqlfmt,tablename);
  136. ret=sqlite3_exec(db,sqlcmd,&errmsg);
  137. @H_404_149@if(sqlITE_OK!=ret)
  138. {
  139. PRINT_TRACE("Createtable\"%s\"Failed:%s.",tablename,errmsg);
  140. sqlite3_free(errmsg);
  141. free(sqlcmd);
  142. @H_404_149@returnret;
  143. }
  144. free(sqlcmd);
  145. @H_404_149@returnret;
  146. }
  147. char*get_sqlcmd(@H_404_149@constchar*tablename,sql_OPTYPEoptype,Employee_Semployee)
  148. {
  149. char*insertfmt="INSERTINTO%svalues(%d,%d,'%s',%10.6f);";
  150. char*selectfmt="SELECT*FROM%swhereid<=%d;";
  151. char*updatefmt="UPDATE%ssetage=%d,registertime='%s',cellphone='%s',"\
  152. "email='%s',resume='%s',salary=%10.6fwhereid=%d;";
  153. char*deletefmt="DELETEFROM%swhereid=%d;";
  154. char*sqlcmd=NULL;
  155. intcmdlen=0;
  156. @H_404_149@if(NULL==tablename)
  157. {
  158. PRINT_TRACE("Invalidparameter:NULLpointeroftablename!");
  159. @H_404_149@returnNULL;
  160. }
  161. //为了简化,给sql语句申请最大空间
  162. cmdlen=strlen(updatefmt)+strlen(tablename)+@H_404_149@sizeof(employee);
  163. sqlcmd=(char*)malloc(cmdlen);
  164. @H_404_149@if(NULL==sqlcmd)
  165. {
  166. PRINT_TRACE("Notenoughmemoryforsqlcommand!");
  167. @H_404_149@returnNULL;
  168. }
  169. @H_404_149@switch(optype)
  170. {
  171. @H_404_149@caseINSERT:
  172. sprintf(sqlcmd,insertfmt,\
  173. employee.sex,employee.registertime,\
  174. employee.email,employee.salary);
  175. @H_404_149@break;
  176. @H_404_149@caseSELECT:
  177. sprintf(sqlcmd,selectfmt,employee.id);
  178. @H_404_149@break;
  179. @H_404_149@caseUPDATE:
  180. sprintf(sqlcmd,updatefmt,\
  181. employee.registertime,\
  182. employee.resume,employee.salary,employee.id);
  183. @H_404_149@break;
  184. @H_404_149@caseDELETE:
  185. sprintf(sqlcmd,deletefmt,employee.id);
  186. @H_404_149@break;
  187. @H_404_149@default:
  188. PRINT_TRACE("Unknownoperationtype:%d\r\n",optype);
  189. free(sqlcmd);
  190. @H_404_149@returnNULL;
  191. }
  192. @H_404_149@returnsqlcmd;
  193. }
  194. inttest(@H_404_149@constchar*dbname,@H_404_149@constchar*tablename,intcount,intistableexists)
  195. {
  196. intret=-1;
  197. inti=0;
  198. intfailcount=0;
  199. longcosttime=0;
  200. time_tttime;
  201. @H_404_149@structtimevaltvStart;
  202. @H_404_149@structtimevaltvEnd;
  203. sqlite3*db=NULL;
  204. Employee_Semployee;
  205. char*sqlcmd=NULL;
  206. char*errmsg=NULL;
  207. time(&ttime);
  208. printf("\r\nStart\"%s\"at:%s",__FUNCTION__,ctime(&ttime));
  209. @H_404_149@if(NULL==dbname||NULL==tablename||0>=count)
  210. {
  211. PRINT_TRACE("InvalidParameter:dbname=%p,tablename=%p,count=%d.",count);
  212. @H_404_149@returnret;
  213. }
  214. //打开数据库
  215. db=open_db(dbname);
  216. @H_404_149@if(NULL==db)
  217. {
  218. @H_404_149@returnret;
  219. }
  220. //判断是否需要创建表
  221. @H_404_149@if(0==istableexists)
  222. {
  223. ret=create_table(db,tablename);
  224. @H_404_149@if(sqlITE_OK!=ret)
  225. {
  226. close_db(db);
  227. @H_404_149@returnret;
  228. }
  229. }
  230. //开启事务模式
  231. START_TRANSACTION();
  232. @H_404_149@for(i=0;i<count;i++)
  233. {
  234. init_employee(&employee);
  235. sqlcmd=get_sqlcmd(tablename,optype,employee);
  236. @H_404_149@if(NULL==sqlcmd)
  237. {
  238. failcount++;
  239. @H_404_149@continue;
  240. }
  241. //开始计时
  242. gettimeofday(&tvStart,NULL);
  243. ret=sqlite3_exec(db,&errmsg);
  244. //结束计时
  245. gettimeofday(&tvEnd,NULL);
  246. costtime+=diff_timeval(tvStart,tvEnd);
  247. @H_404_149@if(sqlITE_OK!=ret)
  248. {
  249. failcount++;
  250. PRINT_TRACE("Excecutesql:%sFailed!Errorinfo:%s.",errmsg);
  251. }
  252. @H_404_149@if(NULL!=sqlcmd)
  253. {
  254. free(sqlcmd);
  255. }
  256. @H_404_149@if(NULL!=errmsg)
  257. {
  258. sqlite3_free(errmsg);
  259. }
  260. }
  261. //关闭事务模式
  262. END_TRANSACTION();
  263. close_db(db);
  264. //打印结果
  265. printf("OperationType:%d,Databasename:%s,Tablename:%s.\r\n",tablename);
  266. printf("Counts\tTotalTime(us)\tAverageTime(us)\r\n");
  267. printf("%-8d%-10ld%-10.6f\r\n",count,costtime,(float)(costtime/count));
  268. time(&ttime);
  269. printf("Finish\"%s\"at:%s\r\n",ctime(&ttime));
  270. @H_404_149@if(0<failcount)
  271. {
  272. ret=-1;
  273. }
  274. @H_404_149@returnret;
  275. }
  276. intmain()
  277. {
  278. intcount=1000;
  279. intistableexists=0;
  280. intret=-1;
  281. char*dbname="employee.db";
  282. char*tablename="employee";
  283. sql_OPTYPEoptype;
  284. optype=INSERT;
  285. ret=test(dbname,istableexists);
  286. @H_404_149@if(sqlITE_OK!=ret)
  287. {
  288. PRINT_TRACE("TestFailed!");
  289. @H_404_149@return0;
  290. }
  291. istableexists=1;
  292. g_employeeid=0;
  293. optype=SELECT;
  294. ret=test(dbname,istableexists);
  295. @H_404_149@if(sqlITE_OK!=ret)
  296. {
  297. PRINT_TRACE("TestFailed!");
  298. @H_404_149@return0;
  299. }
  300. g_employeeid=0;
  301. optype=UPDATE;
  302. ret=test(dbname,istableexists);
  303. @H_404_149@if(sqlITE_OK!=ret)
  304. {
  305. PRINT_TRACE("TestFailed!");
  306. @H_404_149@return0;
  307. }
  308. g_employeeid=0;
  309. optype=DELETE;
  310. ret=test(dbname,istableexists);
  311. @H_404_149@if(sqlITE_OK!=ret)
  312. {
  313. PRINT_TRACE("TestFailed!");
  314. @H_404_149@return0;
  315. }
  316. @H_404_149@return0;
  317. }

猜你在找的Sqlite相关文章