開始
在 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