最近在做sqlite3的二次開發,看到API裡面關於事務的時候,萌生了測試一下事務的開啟與否對插入資料所需要的時間影響的想法,根據sqlite3的api,在後面測試的時候發現對於sqlite3來說事務的開啟與否僅插入1w條資料,時間的差距就已經非常非常明顯了,先說下測試環境:Ubuntu 12.04, sqlite3 3.7.14.1,測試插入1w條資料。
不開啟事務時的測試代碼如下:
int insert_no_trans()
{
printf("<---------------------> \n"
"go into function insert_no_trans()\n");
int j = 0;
for (j = 0; j < 10000; j++)
{
sprintf(sql, "INSERT INTO [dev] ([id], [name], [age])\
values (%d, '%s', %d)", j, "JGood", j);
if(SQLITE_OK != sqlite3_exec
(conn, sql, 0, 0, &err_msg))
{
fprintf(stderr, "INSERT ERROR: %s\n", err_msg);
exit(EXIT_FAILURE);
}
}
printf("INSERT all succussfully!\n");
printf("function insert_no_trans() end. \n"
"<---------------------> \n");
return EXIT_SUCCESS;
}
開啟事務的測試代碼如下:
int insert_with_trans()
{
printf("<---------------------> \n"
"go into function insert_with_trans()\n");
sqlite3_exec(conn, "begin;", 0, 0, 0); //開啟事務
int j = 0;
for (j = 0; j < 10000; j++)
{
sprintf(sql, "INSERT INTO [dev] ([id], [name], [age])\
values (%d, '%s', %d)", j, "JGood", j);
if(SQLITE_OK != sqlite3_exec(conn, sql, 0, 0, &err_msg))
{
is_succeed = false; //失敗之後把標識設為false
fprintf(stderr, "INSERT ERROR: %s\n", err_msg);
break;
}
}
if(is_succeed)
sqlite3_exec(conn, "commit;", 0, 0, 0); //提交事務
else
{
sqlite3_exec(conn, "rollback;", 0, 0, 0); //復原事務
exit(EXIT_FAILURE);
}
printf("INSERT all succussfully!\n");
printf("function insert_with_trans() end. \n"
"<---------------------> \n");
return EXIT_SUCCESS;
}
測試結果大跌眼鏡,時間測試我用的是linux的time命令,在開啟了事務的情況下插入1w條資料的時間僅為0.4s,而在不開啟事務的情況下,由於時間太長,沒有等其執行完,根據.db檔案的大小和已經使用的時間推測,假設單位時間插入同樣多條資料,推算出來的時間高達18分鐘。這已經不在一個數量級了,google了一下這個問題,看到網上有人對此是這麼解釋的,如果未啟用事務,sqlite會每插入一條資料,就往磁碟上面寫一次,在整個執行過程中我也觀察到未開啟事務時程式執行期間硬碟燈一直是亮的,這也映證了這一點。而在開啟事務的情況下,其應該是在對資料全部處理完之後才需要執行一次IO操作,時間自然非常快。