iOS 平臺 SQLite 性能優(yōu)化

開始

在 ios 平臺,數(shù)據(jù)永久化的存儲方式就那么幾種,比如說 coredata,比如說realm,還有nosql的幾種方案,但是很遺憾,nosql的幾種方案支持的功能都還是太少,這樣就讓對它們的選擇顯得十分雞肋——畢竟,如果是簡單的應(yīng)用的話,那就還不如其他方案來的方便快捷——雖然nosql是趨勢。

這次我們來談?wù)劻硪环N比較常見的儲存方案——sqlite,這個東西很厲害,它是一個用c實(shí)現(xiàn)的無需服務(wù)器的sql框架,它就一個文件配合框架就可以實(shí)現(xiàn)一個簡單的數(shù)據(jù)庫了,擁有大部分?jǐn)?shù)據(jù)庫的查詢功能,性能也還不錯。

需求

一般使用的話,sqlite的默認(rèn)配置也是足夠了的,但有一些情況下,我們還是需要更快的體驗(yàn)——比如作為輸入法的詞庫的時候。很多人覺得,用sqlite很快,但作為輸入法的詞庫就顯然太慢了,難道sqlite就不能更快一步嗎?當(dāng)然可以,sqlite的默認(rèn)配之為了適應(yīng)大部分人的使用環(huán)境所以設(shè)置的十分保守,我們可以讓它更快。

Pragma

Pragma 是 sqlite 特有的一個配置語句,與之配合的有一些對應(yīng)的參數(shù),我們在連接數(shù)據(jù)庫后可以對其進(jìn)行修改,但下次連接的時候,還是需要再次配置的。

你可以在這里看到完整的所有 Pragma 參數(shù),不過對性能有重大影響的參數(shù)也就那么幾個,不是很多的。

執(zhí)行 pragma 就像你在 sqlite 里執(zhí)行 sql 語句一樣,沒有返回值。

page_size

1

PRAGMApage_size=4096

大小必須是2的倍數(shù),一般來說,現(xiàn)在應(yīng)該都是默認(rèn)4096了,但如果不是,那你就手動設(shè)置一下,總而言之,你最好把它設(shè)置為與你系統(tǒng)硬盤的分頁大小。

synchronous

1

PRAGMAsynchronous=OFF

關(guān)閉同步,數(shù)據(jù)庫只有在設(shè)備突然斷電之類情況下可能導(dǎo)致數(shù)據(jù)庫損壞——嗯,這種情況,我覺得可以接受。

locking_mode

1

PRAGMAlocking_mode=EXCLUSIVE

當(dāng)不需要同時有多個進(jìn)程同時訪問數(shù)據(jù)庫時(我們就在自己的app里訪問數(shù)據(jù)庫而已)那就不需要默認(rèn)的normal,設(shè)定鎖定模式為exclusive模式,可以保證同一時間只有一個進(jìn)程訪問數(shù)據(jù)庫,這樣可以避免不必要的沖突控制,增加數(shù)據(jù)庫速度。

journal_mode

1

PRAGMAjournal_mode=OFF

日志能夠保證數(shù)據(jù)提交的完整性,一旦提交出現(xiàn)問題,數(shù)據(jù)庫就可以實(shí)現(xiàn)回滾。不過,現(xiàn)在大部分情況下ios的穩(wěn)定性已經(jīng)足夠,如果你甚至都不會給數(shù)據(jù)庫寫入內(nèi)容,那么干脆把日志模式關(guān)閉好了。這樣可以大大加快sqlite的速度。

cache_size

1

PRAGMAcache_size=40960

這個緩存,默認(rèn)是0,也有不少人推薦1,我建議你自己多測試幾次,我自己的感受是有和沒有區(qū)別有點(diǎn),但大小好像沒啥區(qū)別了……

mmap_size

1

PRAGMAmmap_size=40960

配置內(nèi)存映射,但實(shí)際上好像并沒有開啟,這取決于你的sqlite版本。

query_only

1

PRAGMAquery_only=1

如果你和我一樣只是用來查詢,那么就開啟這個選項(xiàng)。

單件模式

說完了參數(shù)配置,我們再來說說其他方面,比如整體的使用姿勢。如果說你在整個應(yīng)用中都不會有其他進(jìn)程訪問數(shù)據(jù)庫(一般也不應(yīng)該有),那么就做一個單件模式,然后保持長鏈接就好了,并沒有必要一直持續(xù)地連接和斷開,同時還可以避免你意外地同時去爭奪數(shù)據(jù)庫資源造成數(shù)據(jù)的丟失和文件損壞。

比如說,這樣:

1

2

3

4

5

6

7classModelManager{

privateinit(){}

staticletsharedInstance:ModelManager?=ModelManager()

……

}

索引

恰當(dāng)?shù)貫槟阈枰?jīng)常查詢的字段進(jìn)行索引,并且避免使用太復(fù)雜的sql語句以確保查詢會使用索引。一個有效的測試方式是使用 sqlite 內(nèi)置的explain功能查看語句的執(zhí)行流程,如果其中包含idx,那基本差不多。

使用 explain 來查看sql語句的預(yù)計執(zhí)行過程

避免不恰當(dāng)?shù)?sql 語句

一般來說,你應(yīng)該只獲取你要獲取的內(nèi)容,不要去做SELECT*FROM這一類腦殘的語句,同時,在獲取內(nèi)容的時候,比如你可能寫的是這樣的:

1

resultSet.stringForColumn("Code")

如果是大量查詢,那么你最好這樣來寫:

1

resultSet.string(forColumnIndex:0)

使用字段索引來獲取內(nèi)容,可以避免查找,大大加快取值速度。

創(chuàng)建表

創(chuàng)建表也有優(yōu)化的地方可以說說,比如如果你的字段能非空,就非空,如果能唯一那自然就最好了!


轉(zhuǎn)自 : https://www.logcg.com/archives/2316.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容