SQLite 是一款開源的 SQL 資料庫引擎,由于其自包含、無服務、零配置和友好的使用許可(完全免費)等特點,在桌面和移動平臺被廣泛使用,
在應用開發程序中,如果想保存點資料,自然而然地就會想到 SQLite,畢竟它擁有非常多的實踐者,這里分享一個在專案開發程序中遇到的 SQLite 讀寫問題——在開發一個小型桌面應用系統時,需求是跟蹤檔案系統中的變更,同時對變更檔案進行相關操作,我們毫不猶豫地采用了 SQLite 來存盤檔案變更資訊,
在開發程序中,SQLite 的資料讀寫都非常順利,沒有什么障礙,然而,當業務邏輯一切就緒開始跑業務時,我們發現軟體處理業務的性能很差,每秒鐘只能處理 10 個左右的業務量,比資料放在記憶體的老系統還慢得多,老系統也還可以達到每秒三十幾個業務,而現在只有三分之一的水平,在有幾千幾萬個檔案變更事件同時涌入的情況下,系統幾近停滯,會出現幾秒鐘一個業務的荒涼場景,這是不能容忍的事情,
經過技術排查,我們發現對 SQLite 的讀和寫都非常慢,最差的情況是從資料庫中獲取一條記錄要花掉 7 秒鐘,十分離譜,于是我們收羅學習了各種 SQLite 的優化技術并應用到了系統之中:
- SQL 操作時采用事務機制
sqlite3_exec(db,"BEGIN TRANSACTION;",0,0,0);
...
sqlite3_exec(db,"END TRANSACTION;",0,0,0);
- 批量操作時,使用sqlite3_prepare而不是sqlite3_exec
sqlite3_prepare_v2(db, zSQL, -1,&stmt, &pzTail);
sqlite3_step(stmt);
...
- 關閉資料庫的磁盤同步寫,降低資料安全性
sqlite3_exec(db,"PRAGMA synchronous = OFF; ",0,0,0);
常見的優化技術都已使用,效果有但不太理想,還是沒有達到老系統的性能,更不要說超過了,
這里需要回顧一下我們的應用模型,業務有并發處理的要求,系統中使用了多執行緒機制,這就出現了對 SQLite 并發多讀多寫的情況,我們查閱 SQLite 的官方檔案,多寫者的情況是不適用的,
https://www.sqlite.org/whentouse.html
至此,是不是說解決的出路就只有使用 client/server 這樣的資料庫了?小應用拖一個巨無霸資料庫,有種頭重腳輕的感覺,
記得資料庫課程的學習中,有提到大型資料庫訪問的 多層模型(N-tier),目的就是更高效地處理資料,那我們的檔案型資料庫有沒有可能擁有 N-tier 的思想?盡管與大型資料庫的方法不一樣,但目的是一致的,我們分析一下現有應用對 SQLite 的讀寫情況,先看圖:

-
操作1
收到檔案系統中的變更資訊,并寫入到資料庫,由于檔案變更資訊是逐條發生的,無法預估事件的開始和結束,來一條寫一條的方式,導致開啟SQLite的事務模式也沒有啥效果, -
操作2
讀取一條記錄并進行業務操作,這里的讀取并非只讀,需要將該條記錄標記為已選取,防止被其他業務處理執行緒讀取而引發重復處理,因此,這一步也存在寫操作,這里是讀一條處理一條, -
操作3
業務處理完畢后,從資料庫中洗掉,這里也是逐條洗掉,
回顧應用的業務操作方式后發現,這些操作都是寫操作,而且還是逐條進行的,問題擺在這里,技術問題還是需要通過技術來解決,在優化的程序中,我們是分步驟進行的——
優化操作1
采用延遲寫的機制,收到檔案變更資訊后,不立即寫入資料庫,先放入快取佇列,等到達一定時間后再進行批量寫入,這樣在大量事件涌入時效果明顯,大大減少了資料庫的寫操作次數,優化操作2
使用快取;好不容易準備好資料庫查詢陳述句,只檢索了一條,太浪費時機,將符合檢索要求的記錄快取起來,同時將記錄被選取的標記放在記憶體中而不寫資料庫,這樣對資料庫來說僅是讀操作,優化操作3
同樣采用延遲寫,將收到的洗掉資訊快取起來,當累積到一定量或者時間后,再進行批量操作,這樣就可以充分利用 SQLite 的事務功能,大大提升寫操作的效率,
增加了這些資料庫訪問層后,資料庫的讀寫性能提升明顯,業務處理能力也達到了預期,超過了舊系統,主要的優化作業差不多就到此結束了,這里引入了延遲寫和快取機制,增加了程式的復雜度,帶來的新挑戰是如何保持快取記錄同資料庫記錄的一致性,為解決這個問題,使用了SQLite的自定義函式:
sqlite3_create_function(...);
通過創建自定義函式,來同步快取記錄和資料庫記錄,比如:在從資料庫讀取業務記錄時,需要排除已經被標為"洗掉"的記錄,
經歷這個專案,我們讓 SQLite 多讀多寫的并發訪問也成為了可能,算是一個識訓,(徐品華 | 天存資訊)
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/286089.html
標籤:其它
