Go With the DBFlow: The Fastest Android ORM Database Library

DBFlow - The Fastest Android ORM Database LibraryThere are several popular ORM database libraries out there (Active Android, Sprinkles, GreenDAO, SugarORM) and nearly every one uses reflection for critical database interactions. We built DBFlow as a more efficient and powerful alternative, and the results have been outstanding – it’s the fastest Android ORM database library.

Reflection And Its Risks

Reflection is “commonly used by programs which require the ability to examine or modify the runtime behavior of applications running in the Java virtual machine”1. In short, it allows us to retrieve properties and data from objects at runtime by inspecting the contents. With this information, for example, we can match a field from a Model object with a column in the database from a specific table.

Performance is a major area of concern with utilizing a data-heavy backend in an application. According to the Java documentation, reflection can’t be optimized by the compiler, and thus takes significant performance hit when choosing it over native execution1.

Annotation Processing: A More Efficient Alternative

In Java, annotation processing is a step run before compile time that gathers all annotations defined for a project and enables processors to perform some action. Writing an annotation processor is no easy task, and there are two significant roadblocks: the learning curve and writing the necessary code. The learning curve is daunting because the Annotation Processing API contains a set of unfamiliar and different name classes than its counterpart, the Reflection API. Second, we have write code that writes code that compiles correctly. From this, writing the processor becomes trial and error until the code compiles correctly and runs as expected. 

DBFlow uses this functionality to generate all sorts of classes and interactions with the database at compile time. This enables the library to run at native speed and becomes as fast as writing the code yourself. Also, generating code is transparent–we can see the code that the app executes and catch errors at compile time. Reflection is difficult to debug, since we will only catch errors at runtime.

DBFLOW: An Overview

    • A wrapper API for SQLite statements, so writing queries with DBFlow feels natural
    • Seamless and simple multi-database support by associating Model classes with a table that exists in that database.

To define a database:

To define a table that corresponds with that database we define:

  • A transaction queue, which will run and queue up database requests in the same thread using the TransactionManager. The transaction queue is ordered by priority so that the most important database interactions can be prioritized.
  • Full SQLite VIEW support
    • First-class Migration support

Migrations are defined by creating a Migration class or by placing a valid SQL statement file in your project’s “assets/migrations/{DatabaseName}/{versionName.sql}” directory. Here is an example of a migration class:

  • Support for type conversion, which allows non-standard SQLite fields to save to the database.
    • Model Containers: classes that imitate and use the blueprint of “Model” classes in order to save data such as JSON. They interact with the database directly without having to convert the data out of its native format before saving.
  • Ultra-efficient relationships: Lazy-loading for maximum performance using ForeignKeyContainers, powerful model caching support, and much more.

Results: The fastest android orm database library.

To show DBFlow’s performance optimization, I performed a series of speed tests in an Android emulator using a few of the most popular Android database libraries2. The test consisted of creating and saving 25,000 records to the database in one large transaction3. I specifically recorded the time it took to save all of the models, and not the time it took to create all 25,000 of them. Afterwards, I record the time it took to load all of them out of the database. The model, AddressItem, had a simple schema:

 

DBFlow - The Fastest Android ORM Database Library

 

DBFlow - The Fastest Android ORM Database Library

 

In our tests DBFlow was the fastest Android ORM database library, consistently performing more than twice as fast as the closest competitor. By using DBFlow, your application will feel snappier, you will decrease your application’s power footprint, and the code you write will feel natural and simple. DBFlow is open source and ready for you to use. Give it a spin and let us know what you think!

Download

Check DBFlow out on Github, or by using gradle, add the Griddle plugin and our maven repo to your root build.gradle:

Add the library to the project-level build.gradle, using the APT plugin and the Griddle plugin:

 

1. http://docs.oracle.com/javase/tutorial/reflect/
2. I used ones that I was most familiar with and those that were more than 500 stars on GitHub.
3. This number seems unusually high. However, when we deal with more complicated models and add relationships between tables, the complexity approaches the test that we do here.


Interested in joining the Raizlabs team making great software? We’re hiring Android developers in Boston and SF.


 

24 thoughts on “Go With the DBFlow: The Fastest Android ORM Database Library”

  1. Nice work with the benchmarks — something I’ve always wanted, but never bothered to write. I stopped working on ActiveAndroid to work on Ollie because I knew I could write a faster ORM with annotation processing, so I’d be interested to see how it ranks in your benchmarks. Is the benchmark test available?

  2. I would like to know how it compares to SnappyDB. As it also says that it is much faster than other implementations. I’ve used it in my projects and it is pretty fast.

    • SnappyDB is NoSQL where as all the comparisons here are SQL.

      I think just by looking at SnappyDB’s comparison with SQL you will see how it compares in speed (Snappy is faster), but a quick look seems like it’s pretty much just an advanced persistent HashMap, which is lacking the features of SQL – I can’t see any possibility of querying the equivalent of a “SELECT * FROM Users WHERE age>40”.

      • Right, that’s why SnappyDB/NoSQL is faster because at the expense of features.

  3. How that compares to greenDao ?

  4. I’m surprised you didn’t do performance tests with Green DAO, which is currently viewed by most Android devs as the fastest ORM for Android. The fact that you mention green dao as a popular android orm early in the post, but don’t benchmark against it makes question your claims.

    My guess is DBFlow performs similarly or perhaps even worse (as greendao has it’s own faster implementation of cursor). I would actually probably be fine and still potentially prefer DBFlow though as GreenDAO lacks many features that they have seemingly refused to add good support for (annotations and enums for one). Also the benefits of compile time generated vs a separate dao generator project isn’t something to be underestimated either.

  5. How this compares to greendao orm ? As far as I know, it’s the fastest one available.

  6. It’s a bold claim to say it’s the fastest one, when you haven’t compared it to GreenDAO… don’t you say?

  7. what about greendao ?
    http://greendao-orm.com

    • Compared in this repo (https://github.com/Raizlabs/AndroidDatabaseLibraryComparison). I didn’t include greenDAO in this post was more from lack of familiarity and having to include its code-generator. I added it post-this blog post and DBFlow is still faster in saving. Also I should have included in the definition of speed as code writing time. greenDAO’s set up and lack of flexibility (if you modify a model, all changes could potentially be lost) also makes DBFlow faster in that regard as it uses annotation processing.

      GreenDAO may be faster at loading times than DBFlow because it is much more aggressive in caching. Not to my knowledge this is not configurable and it stored all 25,000 models in my test in memory. DBFlow allows you to define your own cache and cache size and gives you full control over how its implemented. The point is DBFlow is faster when matching up the caching strategies between the two libraries.

  8. How to specify db path.(default location to save DB)?
    Suppose I want to use SD card for DB?

  9. Is there a way to encrypt the database? In our app, we are using an encrypted version of SQLite. We are using the Sqlite source from the original SQLite source(org.sqlite) and encrypting it. We are not using the Android’s SQlite library(android.database). Is DBFlow internally using the android’s SQLite database?

  10. Hello,
    How to work with Date.

    I want to make query like
    between dates.

    It’s possible with DbFlow.

    plz reply.

  11. Hello,

    Could I use this orm with my java desktop project? This would be great!

  12. I/AuthResponData: saveToLocalDB(), Prepared end: 1455510371346, used:4 sec
    I/AuthResponData: saveToLocalDB(), Prepared end: 1455510377543, used:2 sec

    When using ActiveAndroid, the first action cost 35 sec, the second action cost 25 sec.
    Both are using Transaction and threading.

  13. It is a pain to install. After a day I’m leaving. Can’t we just have a graddle dependency?

  14. Hi, DBflow gives me an error while adding this kotlin extension ‘dbflow-kotlinextensions’ to my gradle file.

    Error:Could not find com.github.Raizlabs.DBFlow:dbflow-kotlinextensions:3.0.0-beta5.

  15. Pingback: Android ORM Performance 2016 - Open Source by greenrobot

  16. use between in that library …

Leave a Comment