设为首页 收藏本站
查看: 634|回复: 0

[经验分享] SQLITE Best practice

[复制链接]

尚未签到

发表于 2016-11-29 07:35:24 | 显示全部楼层 |阅读模式
Recently I’ve been doing quite a bit of work with the Android Sqlite database.  Mostly with the android piece of ormlite.

The Android examples cover some basic Sqlite usage, but they really don’t go into depth with regards to proper usage patters, and more importantly, improper usage patters.  Most examples and documentation is slated towards using very basic database queries, and beyond that, creating a ContentProvider.  What never really seems to be covered is stuff like:


  • Where do you create and store your SQLiteOpenHelper instances?
  • How many should you have?
  • Are there any concerns when accessing the database from multiple threads?
If you look around for information you’ll find a lot of partial or incorrect info.  A great example was forwarded to me by Gray yesterday (he runs the ormlite project).  It was on stackexchange…

http://stackoverflow.com/questions/2493331/what-is-best-practice-with-sqlite-and-android/2493839

The first answer basically says you can connect to the sqlite database pretty much how you want, and the Android system will sort it out for you.  Sqlite has file level locking, which will serialize access and prevent trouble.

This is an example of a little truth and a little experience leave you open to a lot of pain.

Open source is great, by the way.  You can dig right into the code and see what’s going on.  From that and some testing, I’ve learned the following are true:


  • Sqlite takes care of the file level locking.  Many threads can read, one can write.  The locks prevent more than one writing.
  • Android implements some java locking in SQLiteDatabase to help keep things straight.
  • If you go crazy and hammer the database from many threads, your database will (or should) not be corrupted.
Here’s what’s missing.  If you try to write to the database from actual distinct connections at the same time, one will fail.  It will not wait till the first is done and then write.  It will simply not write your change.  Worse, if you don’t call the right version of insert/update on the SQLiteDatabase, you won’t get an exception.  You’ll just get a message in your LogCat, and that will be it.

This issue may be tough to notice.  You have to have more than one distinct connection, and you have to write from more than one thread at the same time.  In most apps that are doing light database updates, that’s a lot of stars to align at the same time.

The first problem, real, distinct connections.  The great thing about open source code is you can dig right in and see what’s going on.  The SQLiteOpenHelper class does some funny things.  Although there is a method to get a read-only database connection as well as a read-write connection, under the hood, its always the same connection.  Assuming there are no file write errors, even the read-only connection is really the single, read-write connection.  Pretty funny.  So, if you use one helper instance in your app, even from multiple threads, you never *really* using multiple connections.

Also, the SQLiteDatabase class, of which each helper has only one instance, implements java level locking on itself.  So, when you’re actually executing database operations, all other db operations will be locked out.  So, even if you have multiple threads doing stuff, if you’re doing it to maximize database performance, I have some bad news for you.  No benefit.

I wrote a test application to show how this all works.


  • Download Android APK File.
  • Github Project Page.
UPDATE!!!! I switched hosting providers and lost the file links. I recreated this app, but it only has 2 buttons. One tests a single helper, and the other tests multiple helpers. Enjoy.

Buttons:


  • One Helper – All threads get one helper object.  Writes are not in batch transactions.
  • Many Helpers – Each thread gets its own helper.  Writes are not in batch transactions.  Since each thread has its own helper, they all have real independent db connections.
If you run the “One Helper” processes, you should see no failures.  If you run the Many Helpers, you should see failures.  Very important: You have to run this on an actual phone!!! On my desktop, its hard to get lock ups.  This is due, I imagine, to significantly better disk performance on my desktop.  I also imagine this contributes to the misconception that Android will just sort of “handle it” with regards to db locking.

Your phone may not see this issue, but if not I assume that’s because the phone performance is significantly better than mine (Samsung Vibrant, Android 2.1) UPDATE!!! Just tried on a Droid Bionic, and it had collisions. If this phone can’t deal, your phone can’t either.

Interesting Observations

If you turn off one writing thread, so only one thread is writing to the db, but another reading, and both have their own connections, the read performance shoots WAY up and I don’t see any lock issues.  That’s something to pursue.  I have not tried that with write batching yet.

If you are going to perform more than one update of any kind, wrap it in a transaction.  It seems like the 50 updates I do in the transaction (this was in the original app version, not the new one) take the same amount of time as the 1 update outside of the transaction.  My guess is that outside of the transaction calls, each update attempts to write the db changes to disk.  Inside the transaction, the writes are done in one block, and the overhead of writing dwarfs the update logic itself.

Performance of database calls is all over the place at different times.  Any serious db calls should probably be in an async process, just in case there’s something else going on behind the scenes.

Anyway, a screenshot (UPDATE!!! This screenshot is old, but I have other stuff to do right now).

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-306847-1-1.html 上篇帖子: sqlite的用法 下篇帖子: ios简单sqlite使用
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表