SQLite在Android一般應(yīng)用中還是比較常用,早期的時(shí)候碰到過不少坑,其中最煩的就是多線程并發(fā)讀寫問題,今天正好整理一下,做個(gè)筆記,也歡迎指正、討論和補(bǔ)充。
一、查詢優(yōu)化
1、wal模式
開啟wal模式,可以實(shí)現(xiàn)并發(fā)讀,且讀寫不阻塞,當(dāng)然寫與寫之間仍然阻塞,該模式需要android3.0+才支持。
當(dāng)開啟了wal模式更新數(shù)據(jù)時(shí),會(huì)先將數(shù)據(jù)寫入到*.db-wal文件中,而不是直接修改數(shù)據(jù)庫文件,當(dāng)執(zhí)行checkpoint時(shí)或某個(gè)時(shí)間點(diǎn)才會(huì)將數(shù)據(jù)更新到數(shù)據(jù)庫文件(執(zhí)行endTransaction時(shí)會(huì)提交checkpoint)。當(dāng)出現(xiàn)rollback也只是清除wal日志文件,而ROLLBACK JOURNAL模式,也就是關(guān)閉wal模式時(shí),當(dāng)數(shù)據(jù)有更新時(shí),先將需要修改的數(shù)據(jù)備份到j(luò)ournal文件中,然后修改數(shù)據(jù)庫文件,當(dāng)發(fā)生rollback,從journal日志中取出數(shù)據(jù),并修改數(shù)據(jù)庫文件,然后清除journal日志。 從以上流程來看wal在數(shù)據(jù)更新上I/O量要小,所以寫操作要快。由于在讀取數(shù)據(jù)時(shí)也需要讀取wal日志驗(yàn)證數(shù)據(jù)的正確性,所以讀取數(shù)據(jù)相對(duì)要慢,但使用wal還是提高了讀取的并發(fā)性。
開啟wal模式后,一定要使用beginTransactionNonExclusive來提交事務(wù)。db.beginTransaction()相當(dāng)于execSQL("BEGIN EXCLUSIVE;"),在當(dāng)前事務(wù)沒有結(jié)束之前任何其他線程或進(jìn)程都無法對(duì)數(shù)據(jù)庫進(jìn)行讀寫操作。當(dāng)開啟wal模式時(shí),使用db.beginTransactionNonExclusive(),相當(dāng)于execSQL("BEGIN IMMEDIATE;"),只會(huì)限制其他線程對(duì)數(shù)據(jù)庫的寫操作,不會(huì)阻塞讀操作。
2、建立索引,推薦看這個(gè)文章,足夠了解索引的簡單使用和優(yōu)點(diǎn)了http://www.trinea.cn/android/database-performance/,總而言之,索引會(huì)增加SQLite體積,且增刪改時(shí)也要維護(hù)索引,會(huì)對(duì)增刪改性能存在一定影響,如果數(shù)據(jù)量不大,不建議使用。使用時(shí)一定要根據(jù)需求建立合適的索引,勿濫用。
3、當(dāng)某張表可預(yù)見數(shù)據(jù)量很大時(shí),可以適當(dāng)?shù)倪M(jìn)行表的細(xì)化、后期可以分表分庫,查詢時(shí)也可以使用異步查詢。
二、批量插入優(yōu)化
1、事務(wù)提交
批量插入,包括更新刪除,一定要加事務(wù),如果不加事務(wù),則默認(rèn)會(huì)為每一次插入開啟一個(gè)事務(wù)并自動(dòng)提交,是非常慢的。
2、開啟wal模式,參見上文中解釋;
3、SQLiteStatement優(yōu)化
我們每次執(zhí)行的sql語句最終會(huì)轉(zhuǎn)化為一個(gè)SQLiteStatement對(duì)象來進(jìn)行處理,可以預(yù)先使用db.compileStatement方法獲取SQLiteStatement對(duì)象并重用,而不是讓系統(tǒng)每次insert都構(gòu)造一個(gè)對(duì)應(yīng)的SQLiteStatement對(duì)象,這樣能夠提高內(nèi)存的使用率。
補(bǔ)充:網(wǎng)上有人解釋“比如insert into xxx,一般情況下執(zhí)行多少次,就要編譯多少次”,關(guān)于這點(diǎn),首先我認(rèn)為不對(duì),我闡述一下我自己的分析:SQLite想要執(zhí)行操作,需要將程序中的sql語句進(jìn)行“預(yù)編譯”。例如批量插入,我們可以使用“顯式預(yù)編譯”來做到重用SQLiteStatement,也就是使用compileStatement方法。其實(shí)重