天天看點

Android資料庫代碼優化(2) - 從SQLite說起從SQLite說起

如果沒有sqlite的基礎,我們隻是從android封裝的sqlite api去學習的話,難免思路會受到限制。是以,我們還是需要老老實實從頭開始學習sqlite.

當我們有一身的sqlite武功之後,再去看android的封裝,就能更清楚如何發揮sqlite的特長。

sqlite的核心隻有一個c檔案,通路的db也存在一個檔案當中。是以,我們完全可以把它嵌入到另外一個程式中。

在mac上,可以通過homebrew來安裝。安裝之後,我們就可以用sqlite3的api來寫代碼了。

我們找個網上找到的最簡單的打開關閉sqlite資料庫的例子:

我們先不管它是什麼意思,先編譯一下試試:

然後運作一下吧,需要本地有個叫contacts.db的資料庫。

輸出為:

從上面的例子,我們可以學習到兩個容易了解的api: sqlite3_open和sqlite3_close.

有了能運作的環境之後,我們就來看看sqlite資料庫引擎的結構吧:

Android資料庫代碼優化(2) - 從SQLite說起從SQLite說起

從這張官方圖上,我們可以看到,除了工具和測試代碼之外,sqlite的核心部分分為三部分:核心,編譯器和後端。

核心部分就是對sql指令的處理的部分,它通過編譯器來編譯成vdbe(virtual database engine)能執行的代碼。

後端是真正對資料庫進行操作的部分,包括b-樹的查找結構等。

喜歡劃重點的同學注意啦,重點來了:調用sqlite3資料庫的代碼優化的第一個點就是将編譯好的位元組碼儲存起來,下次用的時候直接調用。

這麼重要的功能,sqlite3 api中當然有提供,這就是後面我們會大量學習使用的sqlite3_prepare和sqlite3_prepare_v2函數。

android對此也有同樣的封裝,提供了sqlitestatement來實作預編譯代碼的儲存。

有同學問了,我的sql語句并不是一成不變的,語句中的參數經常改變,這樣的話,編譯出來的代碼就沒有用了啊?

這在sqlite3的設計中當然是有考慮到的,編譯好的語句,是可以支援參數的。我們首先使用sqlite3_prepare_v2編譯,然後再通過sqlite3_bind_函數來綁定參數。下次如果換了參數,先調用sqlite3_reset清除掉綁定資訊,然後再重新用sqlite3_bind_來做綁定新參數,就可以了。

一個調用sqlite3實作資料庫操作的功能可以用下面的步驟來套用:

根據業務需求,構造sql語句

調用sqlite3_prepare_v2函數來編譯sql語句

如果有參數,調用sqlite3_bind_*函數來綁定參數

調用sqlite3_step函數來執行一次sql操作,直至所有操作都完成

下次再使用第2步編譯出來的語句時,調用sqlite3_reset函數清理參數。然後重複第3步的操作

最後,調用sqlite3_finalize來銷毀預編譯語句

下面我們直接開始實操,首先先舉個select的例子。

我們以android中聯系人資料庫為例,取其中的calls表的簡化版:

雖然字段很多,我們就關注id和号碼就好。

我們先來一半,我們選_id和number這兩列,然後看看傳回的資料中是不是兩列:

核心代碼如下:

完整版的代碼,便于大家實驗:

下面我們直接調用sqlite3_step去讀每一條記錄,增加下面一段:

如果sqlite3_step傳回的結果是sqlite_row,說明這一次執行取到了一條符合條件的記錄。每次取一條記錄。

完整代碼如下:

輸出如下例:

上面的例子是針對查詢語句的,我們再舉個非查詢語句的例子。比如我們試個插入的例子。

輸出如下:

上面,我們就查詢和非查詢兩種情況,學習了如何使用sqlite3的api。

剩下的工作主要就是構造sql語句以及處理傳回結果了。