WAL是SQLite3.7.0版本引入的一個重大改進。SQLite官網宣稱在很多使用場景下,WAL模型的性能都要好於默認的DELETE模式。下面將針對幾個主要場景對WAL性能做測試,測試的硬件與xxx保持一致。
純寫場景
1) 測試說明
測試簡單更新事務在WAL模式下與DELETE日志模式性能對比,測試語句形如:update user set c1=c1+1 where id=xxx,id為主鍵,串行執行更新。通過執行1w個更新事務,統計程序運行時間。
2) 測試結果
測試時間結果以毫秒計算,TPS是每秒執行的事務數,通過事務數與時間相比獲取結果。
|
WAL模式 |
DELETE模式 |
第一輪 |
55176 |
159196 |
第二輪 |
54442 |
164341 |
第三輪 |
56171 |
162329 |
第四輪 |
56167 |
166117 |
第五輪 |
55969 |
163139 |
平均值 |
55581 |
163024 |
TPS |
179.9 |
61.3 |
3) 結果分析
從測試結果來看,WAL日志模式下,純寫性能要遠遠好於DELETE模式,前者大概是后者的3倍。這個性能差異主要源於每次事務提交,WAL模式只需要將更新的日志寫入磁盤即可,而DELETE模式修改過程中,首先需要將原始數據頁拷貝到日志文件中,並進行fsync;然后再將修改頁寫入磁盤,同時也需要fsync,確保數據落盤,並且還要將日志文件清除。因此,寫事務在WAL模式下,只需要一次fsync,並且是順序寫;而DELETE模式下,需要至少兩次fsync(日志,數據),並且更新的數據可能離散分布在多個page中,因此可能需要多個fsync來完成。眾所周知,fsync調用是非常耗時的,導致DELTE模式下寫性能不如WAL模式。
純讀場景
1) 測試說明
測試WAL模式下,純讀性能數據,測試語句形如:“select * from user where id = xxx”,id為主鍵,對比WAL模式與DELETE模式下讀性能。每個線程執行10w次查詢,統計最終執行時間。QPS為每秒執行的查詢數
2) 測試結果
|
WAL模式 |
DELETE模式 |
||
2線程 |
4線程 |
2線程 |
4線程 |
|
第一輪 |
2847 |
5050 |
4124 |
8168 |
第二輪 |
2730 |
5795 |
3833 |
8074 |
第三輪 |
2688 |
5675 |
3819 |
8077 |
第四輪 |
2959 |
5894 |
3881 |
7787 |
第五輪 |
2836 |
5924 |
3873 |
7958 |
平均值 |
2817 |
5667 |
3906 |
8012 |
QPS |
7w |
7w |
5.1w |
5w |
3) 結果分析
從結果來看,WAL模式下,讀性能要好於DELETE模式,大概提高了將近30%。這說明開啟WAL模式下,對讀性能也有提高。目前我還沒有找到性能提升的原因,后續仔細閱讀源碼后,再做分析。
讀寫場景
1) 測試說明
在WAL模式下,事務提交時實際是以append方式寫wal日志文件,因此讀寫不沖突;而DELETE模式下,寫事務需要寫DB(緩存,文件),與讀事務讀DB(緩存,文件)沖突,因此只能串行讀寫,通過前面的測試可知,WAL模式下,每秒讀寫事務數比例大概是500:1;DELETE模式下,每秒讀寫事務數比例大概是800:1,這里的測試不打算比較讀寫同時存在時兩種模式的對比,而是單獨測試WAL,以讀寫比為500:1場景,看看讀寫的QPS和TPS是否與單獨執行有差異。測試中,讀寫線程都並發讀寫同一張表,讀采用5個線程,主鍵查詢,每個線程執行100w個讀;寫采用1個線程,主鍵更新,執行1w次寫。測試時間的單位為毫秒,QPS和TPS分別為每秒的讀和寫,QPS=500w/時間,TPS=100w/時間。
2) 測試結果
|
WAL模式 |
|
第一輪 |
67543 |
|
第二輪 |
66812 |
|
第三輪 |
72946 |
|
第四輪 |
78844 |
|
第五輪 |
74501 |
|
平均值 |
72129 |
|
QPS|TPS |
6.94w |
138 |
3) 結果分析
通過讀寫比500:1的測試模型,基本保證了讀寫是同時完成的,從另外一方面來說,就是讀寫是充分競爭的。從測試結果來看,WAL模式下,讀的QPS為6.94w,與單獨測試讀7w的性能幾乎無差異;寫的TPS為138, 較單獨測試寫的179略有下降,這可能與設置的讀寫比有關系。通過測試結果可以充分說明,WAL模式下,讀寫是充分並發的,並且幾乎沒有性能損耗。
批量導入場景
1) 測試說明
這個測試主要了了解WAL模式和DELETE模式下,導入數據性能對比。創建2個表,每個表導入10w條記錄,總共20w記錄,觀察導入的時間。
2) 測試結果
|
WAL模式 |
DELETE模式 |
第一輪 |
28019 |
18036 |
第二輪 |
28500 |
17959 |
第三輪 |
28575 |
17578 |
第四輪 |
29078 |
18076 |
第五輪 |
29184 |
17989 |
平均值 |
28671 |
17909 |
TPS |
6975 |
11167 |
3) 結果分析
從結果來看,DELETE模式的批量導入性能要好於WAL模式,這主要源於,DELETE模式記錄的是old-page,而insert操作沒有old-page,所以無需記錄日志,而WAL記錄的是修改頁,所以代價比DELETE模式高。
wal文件大小測試
1) 測試說明
wal模式下,日志采用單獨的wal文件,事務將更新寫入wal文件,事務執行過程中,不斷寫wal文件,直到提交后,才有機會做檢查點,控制wal文件不繼續膨脹。由於端設備,空間資源也非常稀缺,我們來看看wal 模式和delete模式下日志文件對空間的損耗。WAL模式下, wal_autocheckpoint用來控制做檢查點時機,這個參數對WAL文件影響至關重要,測試也圍繞、這個參數展開。
2) 測試結果
場景 |
日志文件容量 |
|
|
WAL模式 |
DELETE模式 |
批量導入(大事務) |
200M |
4k |
主鍵更新(1w行事務) wal_autocheckpoint=1000 |
20M |
19M |
單條更新(單行事務) 更新1w行 wal_autocheckpoint=1000 |
1M |
4k |
單條更新事務 更新1w行 wal_autocheckpoint=4000 |
4M |
4k |
單條更新事務 更新1w行 wal_autocheckpoint=0 |
42M |
無 |
3) 結果分析
從測試結果來看,批量導入大事務時,測試中DB文件200M,產生的WAL日志文件也是200M,由於是INSERT操作,DELETE模式下,日志文件記錄原始數據頁,所以依然為4k,這4k應該是控制信息。對於大事務更新操作,WAL模式和DELETE模式產生的日志量基本相當,只不過一個記錄修改后的數據,一個記錄修改前的數據。對於單行事務,DELETE模式的日志文件基本沒有增長,而WAL模式下,日志文件與wal_autocheckpoint參數相關,默認情況下該參數值為1000個page,每個page_size為1k,因此大約為1M;調整為4000后,日志文件也隨之膨脹到4M;設置為0,亦即關閉檢查點后,更新1w條記錄,將使wal膨脹到42M。因此,無論是WAL模式還是DELETE模式,事務大小都對日志文件大小有影響,對於WAL模式,為了控制日志文件大小,wal_autocheckpoint參數非常重要。