The Android class SQLiteOpenHelper has a method to return a readable database as well as a read and writable database. Currently I am only using writable database and have no issues but I am wondering what the benefit would be to change to using readable only if I am only reading in an async task (or activity).
There might be performance benefits but I have not seen any reference to actual numbers. Also if I keep switching between readable and writable the change has an overhead that might take all the performance advantage away.
Does anybody have any real numbers or experience with this? Is it worth implementing separate access?
Good question. No numbers from me. The nearest explanation (from SQLLiteOpenHandler javadoc)
"This(getReadableDatabase) will be the same object returned by getWritableDatabase() unless some problem, such as a full disk, requires the database to be opened read-only. In that case, a read-only database object will be returned. If the problem is fixed, a future call to getWritableDatabase() may succeed, in which case the read-only database object will be closed and the read/write object will be returned in the future. "
I can't comment on performance benefits but I always try to work on the principle of 'good practice' (or 'best practice' even) for any access to any 'data' sources (text files, DBs or whatever).
Looking at things generically (not Android specific), the decisions to be made when deciding on access level, come down to the operation to be performed as well as any outside influences.
Two examples I can think of...
If an external process may have the
responsibility of maintaining data -
in this case it may have 'opened'
the data source in such a way that
it blocks all but 'read' access by
any other process during the maintenance phase. In this case,
your code will be denied access if
you request read/write access when
it isn't necessary.
The risk of compromising data integrity - hacks into systems from the outside world can be achieved via a security hole using internal code which has read/write access to data when it really only needed to have 'read' access.
OK, those points may or may not have relevance to Android (particularly if your data source is specific to your app) but, as I said, I try to look at things generically and use a 'best practice' approach. If I don't need 'write' access, I don't request it.
Related
I have a huge database and I want my application to work with it as soon as possible. I'm using android so resources are more restricted. I know that its not a good idea to storage huge data in the sqlite database, but I need this.
Each database contain only ONE table and I use it READ only.
What advice can you give me to optimize databases as much as possible. I've already read this post, and except the PRAGMA commands what else can I use?
Maybe there are some special types of the tables which are restricted for read only queries, but principally faster then ordinary table types?
As long as your database fits on the device, there is no problem with that; you'll just have less space for other apps.
There is no special table type. However, if you have queries that use only a subset of a table's columns, and if you have enough space left, consider adding one or more covering indexes.
Being read-only allows the database to be optimized on the desktop, before you deploy it:
set page size, etc.;
create useful indexes;
ANALYZE
VACUUM
In your app, you might experiment with increasing the page cache size, but if your working set is larger than free memory, that won't help anyway. In any case, random reads from flash are fast, so that would not be much of a problem.
Huge is relative. But ultimately a device is constrained on storage and memory. So assuming that huge is beyond the typical constraints of a device, you have a few options.
The first option is to store your huge dataset in the cloud and the connected device can offer views into that data by offering cloud services with something like RESTful APIs from the coud to proffer the data to the device. If the device and app rely on always being connected, you don't need as much local storage unless you want to cache data.
Another approach is an occasionally connected device (sometimes offline) where you pull down a slice of the most relevant data to work on to the device. In that model, yo can work offline and push/pull back to the cloud. In this model, sqlite is the storage mechanism to hold that slice of relevant data.
EDIT based on comments:
Concerning optimizing what you have on the device, see the optimization FAQ here:
http://web.utk.edu/~jplyon/sqlite/SQLite_optimization_FAQ.html
(in rough order of effectiveness)
Use an in-memory database
Use BEGIN TRANSACTION and END TRANSACTION
Use indexes Use PRAGMA cache_size
Use PRAGMA synchronous=OFF
Compact the database
Replace the memory allocation library
Use PRAGMA count_changes=OFF
Maybe I'm stating the obvious but you should probably just open it with the SQLITE_OPEN_READONLY flag to sqlite3_open: I think that SQLite will take advantage of this fact and optimize the behaviour of the engine.
Note that all normal SQL(ite) optimization tips still apply (e.g. VACUUMing to finalize the database, setting the correct page size at database creation, proper indexes and so on...)
In addition, if you have multiple threads accessing the database in your application, you may want to try out also the SQLITE_OPEN_NOMUTEX and SQLITE_OPEN_SHAREDCACHE flags (they require sqlite3_open_v2, though)
Also you need journalling switch off, because data not change http://www.sqlite.org/pragma.html#pragma_journal_mode
PRAGMA journal_mode=OFF
I want to share data across multiple applications, instead of having a ContentResolver->ContentProvider mechanism, I can just define a client library which talks to the process which does the SQLite DB operations right?
What does the ContentProvider brings in here which we cannot achieve by having a Process expose the data?
You can find answer Exact Difference between “Content-Provider” and “SQLite Database”.
But I like to explain this..
What does the ContentProvider brings in here which we cannot achieve by have a Process expose the data?
There is one particular SQLite limitation you should be aware of and that is that SQLite is single-user only. What this really means is that you will need to guard your database from being accessed from multiple threads at the same time. This is generally not a problem in a content provider, since they almost always have a single-threaded implementation.
Also It's good practice to provide the extra level of abstraction over your data to make it easier to change internally. What if you decide to change the underlying database structure at a later time? If you use a ContentProvider you can contain all the structural changes within it, where as if you don't use one, you are forced to change all areas of the code that are affected by the structural changes. Besides, it's nice to be able to re-use the same standard API for accessing data rather than littering your code with low-level access to the database.
You can check the thread below:
Exact Difference between "Content-Provider" and "SQLite Database"
My app needs to store data on the phone, but I'm not sure what's the more efficient method. I don't need to search through the data or anything like that. I just need to be able to save the app's current state when it closes and restore when it's back up. There is between 1mb and 10mb worth of data that will need saving.
There are basically a bunch of custom classes with data in them, and right now I have them as Serializable, and just save each class to a file. Is there any reason for me to change that to store it in SQLite?
If you where to use sqlite you could save as you go, and know that whats in the DB is pretty much uptodate if the app/activity holding the data is suddenly killed by the os. Other that that I cant see and obvious reason to use sqlite for your use-case.
Also for the sql approach you have a clear cut way to change the structure of your domain objects at a later time and to migrate the data from a old to a new version of your database. This can be done using serialized objects as-well, but then the objects needs to be duplicated, both new and old at the same time. And that to me sounds very very scary and messy, especially considering that you might need to go from version x to y, so you might end up with some pretty tricky problems if you ever need to update the domain objects.
And I can honestly not see any benefits of using the flat-file/serialized approach.
You mention in your question that the data is only meant to save the state of the app, therefore my initial response would be to keep it on the devices especially since you mention that the file size would not be much more than 10MB, which is quite reasonable.
So my answer to you would be to keep it as is on the device. If your usage of the information changes in the future, you should then reconsider this approach, but for now it's totally logical.
If you're only saving serialized classes, you could use an ORM mapper as discussed in this thread . This saves you the inconvenience of writing your own mapper and is easily extendable to new classes. Also, if your requirements change, you COULD lookup data.
The only reasons for changing your system to SQLite would be more comfort and maybe a more foolproof system. E.g. now you have to check if the file exists, parse the contents etc. and if you'd use SQLite, you don't have to verify the integrity of the data and Android also helps you a little. And you could use the data for other causes, like displaying them in a ListView.
Sqlite on android lets you access the database from multiple procs for reads, but if you're currently writing from one process, reads and writes from other procs will throw an exception because the first write has a lock on the db.
By "procs" I mean other threads in the same app.
Is there a standard way to have the other threads simply wait until the database is available again, possibly with a specified timeout, rather than throwing an exception?
Anticipating the "why are you doing it that way?" answers, its just the way we're doing it, and that's it. We're also not going to use a content provider. Just want a way to synchronize db access.
Assuming there's no standard way to do it, we'll probably wind up writing a wrapper around the db calls to do some thread synchronization.
So long as you're using the same SQLiteDatabase object, the synchronisation is done for you.
So if you access the object via a singleton, there should be no problem. Though you may want to add some further logic if you want to implement a timeout, e.g. wait/notify or something similar.
Or you can use another database that does support it, like H2. I know it may sound like a strange idea. But according to my initial test it works well (on the emulator as well as on the device), and is actually not slower. Except for opening and closing a database, which is currently quite slow, about 1 second, but that has other reasons, and hopefully will get fixed in the next version.
I am developing an application that periodically sends information to an external server. I make a local copy of the data being sent, for backup purposes.
What is the best option to store the data in terms of saving battery life? Each data submission is a serialized object (the class has 5 fields, including a date, numbers and strings) of about 5K-10K.
Any other idea?
I don't believe it matters whether you use SQLite or a File, because the SQLite db is simply a file on the system (stored in /data/data/<your_package>/databases/). You'll need to commit to the db at the right times, just as much as you would need to save a file to the hard drive at the right times. In other words, one way or the other you can use just as many hard drive writes.
I think that what you choose depends more on what sort of data you are saving. If you need the powers that having a db can bestow (such as querying), then by all means use SQLite. However, if you don't need a db, or you've got data that varies wildly (and can't be easily setup in a relational database) then I'd go with files.
What I can tell you for sure is that you should not use serialization for saving a file, if that is the route you choose to go. Android serialization is slow, slow, slow and creates large files. It is much better to either write your own XML or JSON format for performance reasons.
I have no idea in terms of battery life directly but one criteria would be which is easier to manage? Fewer operations to manage the data would mean fewer CPU cycles and in turn longer battery life.
I would say the SQLite option is easier. You can put a date column in the SQLite table which stores your data which makes removing old submissions which you don't need any more very easy - and all handled via the native SQL library. Managing a whole load of file - or worse a single file - with your own Java code would be much more work.
Additionally, you can write data the to database and just forget about it until you need to read it again. If you're storing data in files, you'll need to work out when you should be reading and writing files in terms on the Android application life cycle. If you're worried about battery you probably wouldn't want to write files more often than you should, and cache data in memory, but you'd need to make sure you didn't lose any data when your app is Paused or Destroyed. In my opinion it's much easier to use an SQLite database and not worry about any of this.
Is your application multi-threaded? If you have multiple threads accessing the data store then I would go with SQLite. Let SQLite worry about locking issues.