該試試 SQLite 的 5 個理由

鄭芸發表於2016-06-14

如果你還沒聽說,SQLite是一款能夠實際運作在真實產品環境中的驚豔的資料庫。在這篇文章中,我會列出5大理由來解釋為什麼我認為你應該在2016年試試 SQLite。

簡便管理

你管理過一個Postgres資料庫嗎?為了確保資料庫伺服器得到恰當設定(共享資料緩衝區,有效快取大小,工作記憶,維持工作記憶,緩衝機制…)你需要明瞭相當多的事項。升級也會是一個可怕的過程,你也許需要離線你的資料庫,執行一個程式來阻止它升級,並希望等你重啟時它仍可以執行。更進一步說,你知道你的 postgres 資料庫儲存在哪嗎?你可以指著一個地方說,「這就是我的資料庫嗎」?

(現在,我們都知道在很多情況下只有 Postgres (或MySQL, Oracle, SQL Server等)可以滿足應用上的要求。這裡我的目的並不是說SQLite另有規定。而是我只想強調相比較於傳統的資料庫伺服器,管理一個SQLite db資料庫的不同點。

SQLite管理起來非常簡便——它是一個單一的檔案(或者有時是一個檔案 + 事務日誌)。檔案格式在主要的版本中非常穩定,所以如果我在SQLite3.0.0版本上(2004年推出的版本)有資料庫檔案,我可以使用 SQLite 3.10.0版本讀出它。如果我想把資料檔案裝在U盤中隨身攜帶,我可以拷貝檔案,或者目前更好的是我可儲存在我的dropbox資料夾。如果我每天晚上都要備份這些檔案,我只需把資料庫檔案同步到S3。如果我想共享我正與我同事合作的資料分析,我只需傳送給他們這個資料庫檔案的一個我已準備好的副本。資料庫在一個單一的檔案中,且保持穩定的格式是SQLite的一大特性。

而且,SQLite設定起來也很方便。 SQLite的功能可以用兩種方式來管理:編譯標誌 和 編譯指示語句(執行時配置)。這裡沒有指明的配置檔案,你只需把你想要的功能構建成庫,然後在建立資料庫連線時配置這些執行時選項。

不斷改善目前已堅若磐石的穩定性

SQLite是由幾個真正的軟體工程師大神主動開發。並以驚人的速度不斷增加高質量的新功能。就在前不久SQLite通過 json1擴充來支援JSON資料(獲取更多關於在 Python上應用它的文章,請點選這篇文章)。SQLite還發布了一個改進的全文檢索的擴充套件版本,其中包括使用BM25演算法的結果排序。

除了增加新的功能,SQLite開發者也正在努力使庫的使用更高效。在3.8.11版本,發行說明包含這條宣傳語:

SQLite如今的速度是 3.8.0版本速度的兩倍,是 3.3.9版本速度的3倍。

儘管有了這些變化和改進,SQLite鮮少出現 bug。SQLite測試套件被廣泛認為是行業內最佳之一,在開發者發現這個令人印象深刻的檔案後,SQLite如何測試的頁面經常出現在HackerNews上。

可擴充性和可控性

我個人最喜歡的特性是它的可擴充套件性。因為SQLite是由你的應用程式插入的,它執行在相同的地址空間,可以代表你執行應用程式程式碼。無論是Python標準庫SQLite驅動,pysqlite,和替代驅動apsw提供的APIs來定義自定義的SQL函式,聚合函式和排序規則。apsw更進了一步,提供APIs定義虛擬表和虛擬檔案系統!

舉一個實際的例子,假設在你的資料表中有一列儲存 URLs,你希望確定哪個是最常見的主機名——如果你正使用不同的資料庫,你會被迫去寫一個複雜的正規表示式,一個字串操作函式的組合,或把資料放入你的應用程式並在程式碼中進行運算。而有了SQLite,你可以在Python中定義一個主機名的功能,然後使用它來建立一個簡單的計數查詢:

您還可以建立聚合函式,它接受 0..n 值,並生成一個單個輸出值。例子可能是計算標準偏差、通過用一些方式處理值來產生字串、或者做一些型別的分類等等。

虛擬表,目前只受apsw支援,允許你在程式碼中定義一個表,然後把它當作一個正常的SQL表來查詢,即使後臺的資料完全是動態的。舉例來說,我寫了一個簡單的虛擬表,可以允許你像查詢SQL表一樣來查詢Redis.

你也可以寫同名的函式,其中函式返回0..n行結果。正規表示式搜尋函式也許是個例子,它處理輸入值和產生匹配令牌的行。我寫了一個庫,sqlite vtfunc,它使得寫這些型別的函式變得極其容易。

SQLite的每個方面都可以被你的應用程式操作。

Lightning fast

SQLite執行起來很快。它在同一個機器上執行,所以在執行查詢和讀出結果時沒有網路管理費用。它在同一個地址空間執行,所以沒有有線協議,序列化或需要通過UNIX套接字通訊 

SQLite的速度彌補了他的最大的缺陷,就是資料庫檔案鎖定為寫。正因為寫資料的速度快到不可思議,只有當存在大量的併發寫程式時,資料庫的鎖定才會成為一個問題。

WAL ( Write-Ahead Logging  預寫式日誌記錄 ) 模式

3.7.0版本的SQLite新增了一個新的日誌記錄方法,使用預寫日誌記錄。這本身不是什麼真正值得興奮的新聞,但這意味著對於 web應用(或任何併發機制)開發者來說,讀程式和寫程式不再相互限制。或者換個方式來說,讀和寫可以發生同時。如果沒有有 WAL 模式,為了寫這個資料庫,寫程式將要求獨佔訪問權,在撰寫完成前,這個資料庫無法被訪問。

下面是一個例子來圖解兩者的不同,假設我們有兩種程式狀態,寫程式和讀程式。寫程式開始一個專有事務(表示有撰寫的意圖)。接下來,讀程式會開啟一個事務,然後讀程式嘗試去釋出一個篩選的狀態:

Journal mode = “delete” (the default):

  • Writer: BEGIN EXCLUSIVE
  • Reader: BEGIN
  • Reader: SELECT * FROM foo; Error: database is locked

Journal mode = “wal”:

  • Writer: BEGIN EXCLUSIVE
  • Reader: BEGIN
  • Reader: SELECT * FROM foo; Returns table contents

然而,值得注意的是,即使你不具有WAL模式,寫通常發生在毫秒間。這是一個如此短的時間來讓你注意到問題,如果你有非常高的併發或有很長的事務要寫。

額外的原因:BerkeleyDB

BerkeleyDB的SQLite的整合甚至可以給需要訪問併發資料庫的應用程式開發者們提供更好的效能,因為BerkeleyDB不是鎖定整個資料庫,而是隻需要鎖定單個頁面。這使得BerkeleyDB在載入併發資料庫時有更高的吞吐量,只要事務沒有爭奪同一頁資料。BerkeleyDB還支援多版本併發控制(MVCC),它允許讀的操作繼續發生在正在運作寫的事務的資料頁。

BerkeleyDB另一個好處是效率的提高。換句話說,BerkeleyDB可以使用更少的系統資源和執行更少的系統呼叫。你可以在這份白皮書簡要技術概述中找到更多的細節。

BerkeleyDB的SQL介面是SQLite的一個插入式替換方式,並支援相同的APIs和功能。BerkeleyDB提供了一些附加功能,比如複製(SQLite有備份實用工具,但我的理解是,它不如BDB強大)、加密,當然還有包括BerkeleyDB自身所有的功能。

BerkeleyDB使用起來的一大缺點是對配置值非常敏感,並且獲取正確的頁面大小、快取大小等其他設定需要深厚的知識。另一個缺點是授權許可——閱讀更多關於BerkeleyDB的授權許可,可檢視Oracle的授權頁面

關於編譯使用BerkeleyDB編譯Python SQLite驅動的操作指南,可以看看這個帖子

結束語

我希望你可以試一試SQLite 。不要相信FUD(Fear,Uncertainty,Doubt,一種別有用心的打擊手段)對它的描述:沒有生產價值,或者不適合在web應用上使用。

如果你想了解更多,SQLite本身有一個好的描述: when to use SQLite, 它總結了一個單子,什麼情況下RDBMS可以更好地工作。我也曾寫過一篇同樣的短文叫做:SQLite: Small. Fast. Reliable. Choose any three  ,你可能會喜歡。最後,你可檢視我帶「sqlite 」文章來看更多熱文。

感謝你抽出寶貴的時間來閱讀,如果你有任何問題、評論或者建議歡迎在評論區留言~

打賞支援我翻譯更多好文章,謝謝!

打賞譯者

打賞支援我翻譯更多好文章,謝謝!

任選一種支付方式

該試試 SQLite 的 5 個理由 該試試 SQLite 的 5 個理由

相關文章