高性能安卓數(shù)據(jù)庫框架實(shí)戰(zhàn)

????安卓數(shù)據(jù)庫框架確實(shí)很多,我使用過許多安卓數(shù)據(jù)庫框架,無論是基于sqlite數(shù)據(jù)庫框架ormlite,greendao,litepal。還是nosql的數(shù)據(jù)庫框架snappy db,objectbox。我實(shí)戰(zhàn)此數(shù)據(jù)庫框架的目的就是在性能上向這些優(yōu)秀的數(shù)據(jù)庫框架靠近,在易用性做到比他們更好。接下來,我將介紹該框架基本用法以及講述我為什么要這么寫的目的。

? ? 首先我們看看這個(gè)數(shù)據(jù)庫框架與幾大主流的數(shù)據(jù)庫框架的性能對(duì)比,結(jié)果如下所示:

????自定義數(shù)據(jù)庫框架插入十萬條數(shù)據(jù)時(shí)間差為2651毫秒

????自定義數(shù)據(jù)庫框架更新十萬條數(shù)據(jù)時(shí)間差為40318毫秒

????自定義數(shù)據(jù)庫框架刪除十萬條數(shù)據(jù)時(shí)間差為1401毫秒

????realm插入十萬條數(shù)據(jù)時(shí)間差為2063毫秒

????realm更新十萬條數(shù)據(jù)時(shí)間差為89853毫秒

????realm刪除十萬條數(shù)據(jù)時(shí)間差為106660毫秒

????ObjectBox插入十萬條數(shù)據(jù)時(shí)間差為444毫秒

????ObjectBox插入十萬條數(shù)據(jù)時(shí)間差為1444毫秒

????objectbox刪除十萬條數(shù)據(jù)時(shí)間差為275毫秒

????snappyDB插入十萬條數(shù)據(jù)時(shí)間差為618毫秒

????litepal插入十萬條數(shù)據(jù)時(shí)間差為220679毫秒

????litepal更新十萬條數(shù)據(jù)時(shí)間差為182659毫秒

????litepal刪除十萬條數(shù)據(jù)時(shí)間差為16199毫秒

????rmlite插入十萬條數(shù)據(jù)時(shí)間差為219876毫秒

????ormlite更新十萬條數(shù)據(jù)時(shí)間差為176420毫秒

????ormlite刪除十萬條數(shù)據(jù)時(shí)間差為154728毫秒

?????greendao插入十萬條數(shù)據(jù)時(shí)間差為212657毫秒

?????greendao更新十萬條數(shù)據(jù)時(shí)間差為158880毫秒

?????greendao刪除十萬條數(shù)據(jù)時(shí)間差為140119毫秒

? ? 可以看到這個(gè)框架是基于sqlite數(shù)據(jù)庫框架性能最高的,設(shè)置與realm這樣非sqlite的數(shù)據(jù)庫框架也有的一拼,當(dāng)然,話又說回來,這與像objectbox這樣的nosql數(shù)據(jù)庫框架還相差甚遠(yuǎn),這也是下面這個(gè)數(shù)據(jù)庫框架奮斗的目標(biāo)。那就有兩個(gè)問題,這個(gè)框架究竟怎么用,又是怎么實(shí)現(xiàn)的了。

? ? 其實(shí)他用法很簡單,首先實(shí)例化,代碼如下:

????UserDao dataHelper = DaoManagerFactory.getInstance().getDataHelper(UserDao.class, User.class);

? ? 通過一個(gè)工廠方法來根據(jù)XX實(shí)體類,XXDao實(shí)體類來產(chǎn)生相應(yīng)的實(shí)體類類型。這個(gè)和ormlite,greendao是一致的,一行代碼就讓您產(chǎn)生數(shù)據(jù)庫操作類,不需要進(jìn)行任何的其他配置。這個(gè)工廠方法實(shí)現(xiàn)就是通過Java實(shí)現(xiàn)多態(tài)兩個(gè)厲害武器——反射與泛型實(shí)現(xiàn)的。

? ? 接下來我們看看實(shí)現(xiàn)批量插入10w條數(shù)據(jù),相應(yīng)代碼如下:

????List users =new ArrayList<>();

????UserDao dataHelper = DaoManagerFactory.getInstance().getDataHelper(UserDao.class, User.class);

????for (int i =0; i <100000; i++) {

????User user =new User("jett","abc123", i);

????users.add(user);

????}

????dataHelper.insertValues(users);

?如果用傳統(tǒng)的db.insert(XX)contentValue形式,然后通過傳統(tǒng)循環(huán)的形式來插入數(shù)據(jù),這樣性能一定是龜速。我們這里為何不用原生sql的方式了,原生sql提供了批量插入的形式了,形式如下:

insert?into?persons???

XXX

values??

(200,'haha'?,?'deng'?,?'shenzhen'),??

(201,'haha2'?,?'deng'?,?'GD'),??

(202,'haha3'?,?'deng'?,?'Beijing');?

接下來的代碼就簡單了,就是拼接字符串,但是,在android 原生api做了一定的限制,一次性插入sql不能太長。最多只能插入500個(gè)字,因此拼接sql用雙層循環(huán)罷了。

? ? 接下來是批量更新10w條數(shù)據(jù),用法如下:

????UserDao dataHelper = DaoManagerFactory.getInstance().getDataHelper(UserDao.class,User.class);

????for (int i =0; i <100000; i++) {

????Useruser =new User("jason","bbc332", i);

????values.add(user);

????}

????List wheres =new ArrayList<>();

????for (int i =0; i <100000; i++) {

????Useruser =new User(i);

????wheres.add(user);

????}

????dataHelper.updateValues(values, wheres);

? ? 與insert同理可知,利用普通update加where的形式性能得不到很好的保障,我這里的利用技術(shù)棧為:

? ? Update xxx set xxx where id in (xxxxxxx)

? ? 有了這樣的思想作為指導(dǎo),一樣就是拼接sql的事情了,但是了這里要說一下,我對(duì)id的必要性判斷沒有做,后續(xù)需要優(yōu)化

? ??? ? 接下來是批量刪除10w條數(shù)據(jù),用法如下:

? ??UserDao dataHelper = DaoManagerFactory.getInstance().getDataHelper(UserDao.class, User.class);

????for (int i =0; i <100000; i++) {

????User user =new User("jett","abc123", i);

????users.add(user);

????}

????dataHelper.deleteValues(users);

? ? 與update實(shí)現(xiàn)原理有異曲同工之妙,這里就不做過多贅述。

? ? 最后總結(jié),此數(shù)據(jù)庫框架就是利用好sql語句優(yōu)化,來利用sqlite的最大性能。如果要提升數(shù)據(jù)庫框架與objectbox并駕齊驅(qū)的話,那么就需要利用ndk來構(gòu)建nosql數(shù)據(jù)庫。是接下來任務(wù)。代碼地址:

????https://github.com/zengchiwen/zcwdb

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容