Wild Storage | Part 1 — Performance for queries

Dinorah Tovar
Knowing Android
Published in
6 min readMar 5, 2021

For Android developers

Easy data layer for every Application, here is the list of the blogs in this series:

This image is from Unsplash

This is the first part of the series “Wild Storage for Android developers” today we are gonna discuss Performance in the queries specifically for how to get better instances and responses, and especially how we should handle the database with an easy approach as a performance-wise solution.

Usually, for mobile, this is a common approach, the user may launch some type of action and we will call an API and this API will return a result that we may be written to a file, shared preferences, or a database, here is the first important part for the data layer of your app, the Network layer, if you are interested in more information about you can check my past serial “Practical Network for Android Developers”

And the second part is the Local Data Layer that is handled by internal storage, for this part we are not gonna talk about files, and we will discuss SharedPreferences in the third part of this serial.

We may have multiple types of cache and some are specifications to Network, but we may have Database caching, some examples are

  • CDN — Global network of edge locations to deliver a cached copy of your APIs content
  • DNS — Every domain request made on the internet essentially queries DNS cache servers in order to resolve the IP address
  • Database caching — Database provides an impactful factor in your app performance.

Many Databases

There are too many databases some are relational and others non-relational, for many years the fixed solution for Android development was SQLite, SQLite is an incredible tool, scales well, and is wildly used in multiples companies, but for Android, there were some problems, for example, runtime crashes, the boilerplate was enormous, and after some consideration, many alternatives were created for example

  • SQL Delight — Typesafe alternative for SQL statement, that understands your existing SQL schema.
    TypeSafe — Typesafe Kotlin APIs from your SQL statements
    Kotlin first — even for Multiplatform
    Threading — support for Coroutines, RxJava, and Android Paging
  • Room — Google alternative to SQLite that mostly a wrapper of the original SQLite implementation
    Compile-time — verification of SQL queries
    Less boilerplate — and follows the DAO pattern
    Threading — support for Coroutines, flows, and so many other things
  • Realm — Non-Relational and recently handled by MongoDB with an alternative for Sync on their own cloud
    Threading — Executables for transactions -> executeTransactionAsync
    Listener — OnChangeListener
    Has a browser — RealmBrowser
    Easy Encryption — Using KeyChain can happen really easy

Performance

But today, we are gonna talk about Room as one powerful solution with great performance for Android Development, Room works as an abstraction layer for SQLite, many applications use SQLite as a cache of relevant content from an enterprise RDBMS, there are some reasons we need to talk about why is a powerful solution.

  • The addressed file in Insert, Update or Deletegenerates a small edition and only overwrites the parts of the file that change, reducing write time and wear on
  • All the Insert, Update or Delete can be created based on concise SQL queries instead of procedural routines, causing the least error-prone details
  • The database can be updated and migrated making it super flexible to address changes with the idea of preserving backward compatibility, if you are interested in Migrations and how to handle it you can review my past blog post Select, Insert, Indexes and Foreign Keys on Room Migrations
  • We can address performance problems, using Index, Foreign keys, and multiple other tools of integrity, avoiding redesign and revamping efforts

Let’s talk about how to manage a better query performance using Room, there are some basic rules that we may need to address:

Take what you need
This is one of the most basics performance-wise actions we can take about extracting data from our database. Let’s imagine that we have a Product table that contains multiple data like name, price, type, promotions, offers, and many other things, It may be really simple for us to take all the information from the table indiscriminately, what so ever, by using, SELECT * you can return useless data that will be only using space in Runtime memory.

Accessing databases and fetching data from them has an IO cost on the performance of our applications and if we are not careful we may end up with tons of wasteful IO cycles on the DB, also take into consideration that a SELECT * can make your query slower.

Foreign keys, Primary keys, and Relations
Foreign keys are more focused on the integrity of the database, but with Indexes, they boost performance, inside Room adding a Foreign key will not force you to add an Index key, but you should create indexes on all Foreign key fields to improve look-up times.

Relation in Room gives us the opportunity to have “embed” some Entity inside a Data Class, @Relation which works as an annotation, when the info is returned from a query, all of its relations are also fetched automatically.

Transaction
Transactions are annotations that can be used in functions to execute the non-abstract method of an abstract Dao class, the derived implementation of the method will execute the super method in a database transaction.

Transactions help us to handle a block of code that needs to be fully successful to be marked as that, the transaction will be marked as successful unless an exception is thrown in the method body. We will talk a little deeper about how Transactions work under the hood in the second part!

Coroutines ✨
Sounds like a pretty straight forward process to run all our queries in a secondary thread, to not block the main thread and this can be applied to anything inside Room just adding the keyword suspend

From the insert to the transaction, we need to verify how the threading and the concurrency of the queries and functions are handled, but that will be addressed in the second part of this serial!

If you have a question about handle Foreign keys, migrations, and insertions on Room, you can review my past blog post about this topic Select, Insert, Indexes and Foreign Keys on Room Migrations

If you need help, I’m always happy to help, you can find me here:
Medium as Dinorah Tovar
Twitter as @ddinorahtovar
StackOverflow as Dinorah Tovar

Happy Coding! 👩🏻‍💻

--

--

Dinorah Tovar
Knowing Android

Google Developer Expert on Android | Doing Kotlin | Making Software 24/7 | Kotlin Multiplatform | She/Her | Opinions are my own, and not my employer