????安卓數(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ù)。代碼地址: