El siguiente es un artículo que hace la comparación al usar la base de datos en Android de distintas formas. Nativamente el framework de Android provee una clase llamada OpenHelper desde donde podemos empezar a utilizar la base de datos. Por otra parte, hay librerías ORM (Object Relational Mapping) que nos entregan una capa de métodos simplificados para trabajar con la base de datos. Para esta ocasión se escogieron 2, Sugar ORM y Realm. Hay otros ORM, pero, se escogió Sugar porque es ridículamente simple de usar y Realm por la popularidad que tiene.

Primero vamos a hablar acerca de cómo es usar cada uno, y luego hay un benchmark de rendimiento.

¿Qué tanto me duele implementarlo?

El OpenHelper es una espina en la planta del pie de la arquitectura, Sugar es tu amigo con el que haces trabajos y vas a fiestas, y con Realm hay que acostumbrarse pero definitivamente lo vale. El experimento consistió en hacer el mismo proyecto 3 veces, una app simple que maneja pendientes, pueden ver los proyectos acá:

Realm Sugar OpenHelper
Documentación Excelente Justo lo necesario No sé si llamarle documentación
Curva de Aprendizaje No basta con leer el ejemplo, para sacarle provecho hay que leer bien Con el ejemplo del «getting started» es suficiente Básicamente hay que saber SQL
Beneficios Tienes listeners de cambios en los datos que funcionan con POJOs e hicieron un excelente adapter para las RecyclerView Tan simple como siempre trabajar con POJOs ¿No añadimos librerías?
Contras Hay que abrir la instancia antes de usarla y después acordarse de limpiarla Hay que compensar la falta de features utilizando muy bien Android Para generar una arquitectura digna hay que ser muy bueno en Java
Crear las tablas Automático Automático Manual

Me gustaría tomarme unas líneas para contarles cosas interesantes, más allá de la tabla resumen.

Una cosa fea del OpenHelper es que no puedes derechamente tener una app simple, hay que pensar delicadamente cómo hacer que las propiedades de JAVA trabajen a tu favor. Para empezar hay que crear las tablas, entonces lo mejor sería genera una clase que herede de Application y sobre escribirle el método onCreate para que genere las tablas. Esto no es de experto, pero descarta a cualquiera que esté empezando. Una cosa buena es que no es necesario verificar que existan las tablas.

Cuando estaba pensando en cómo hacer las transacciones me di cuenta de que siempre iba a necesitar el contexto para inicializar mi clase que extiende el OpenHelper y que adicionalmente las transacciones se deberían de hacer de forma asíncrona. Así que quedé en el dilema de cómo heredar de 2 clases, una que me inicializara el OpenHelper y otra que recibiera los parámetros de la AsyncTask ajustados para cada tipo de operación. Al final llegué a esta clase:****

abstract class PendingTransactor<Param, Progress, ResultObject> extends AsyncTask<Param, Progress, ResultObject> {

    final PendingOpenHelper openHelper;

    PendingTransactor(Context context) {
        openHelper = new PendingOpenHelper(context);
    }
}

De esta forma, cualquier transacción (crear, leer, actualizar) puede recibir y devolver los parámetros más adecuados de la AsyncTask al heredar esta clase base. En resumen, tener que resolver este tipo de problemas hace que los que no somos expertos en Java se nos dificulte en vez de facilite.

Adoro Sugar porque es ultra simple, se basa fuertemente en integrarla utilizando el AndroidManifest. Al principio se siente como algo extraño, pero con el tiempo creo que es un gran acierto, porque es el Java el que se ensucia, así que entre más limpio lo tengamos, da lo mismo que sea medio raro, a la larga es mejor. Sugar a diferencia de Realm mantiene una clave única id de forma autoincremental. En Sugar y Realm para que un POJO funcione como objeto representante de una entidad en la base de datos, es decir un modelo, esa clase tiene que heredar una clase de la librería. En Sugar esto es magnífico porque las clases heredan un método .save(); permitiéndonos que con los getter y setter podamos modificar el objeto y luego simplemente guardar los cambios.

Ahora, Sugar palidece un poco al lado de Realm, en comparación a features. Algo incomodo de Realm es que hay que abrir una instancia y después limpiarla (generlamente en onStop), pero las funcionallidades que tiene definitivamente lo valen. Realm tiene un listener que te permite saber cuándo ocurrió un cambio en cualquier objeto que cumpla las condiciones de una query. Y mejor aún, hicieron un adapter para la RecyclerView que es mágico, me arriesgo a decir que viene a ser algo así como la versión local de lo que es Firebase. El adaptador funciona en base a una query, si algo pasa con algún objeto que lo haga cumplir las condiciones de la query o dejar de cumplirlas, la lista se actualiza de forma automática: simplemente entran filas y salen por pura auto-magía.

¿Qué tan rápido son?

El experimento acá consistió en hacer 10 mil inserciones y lecturas en la base de datos, para ver cuánto se demoran. Pueden reproducir los resultados en el branch benchamrk de cada proyecto si gustan. Los resultados son el promedio de 3 intentos por cada dispositivo (cosa que la verdad no importa mucho porque las diferencias eran de 1 segundo).

10 mil inserciones en segundos:

Realm Sugar OpenHelper
Nexus 5X API 23 (emulador) 25 49 35
Nexus 5X API 22 (emulador) 13 44 23
Sony Xperia C3 API 22 94 146 116
Galaxy Note 3 Neo API 19 89 114 104

El resultado es super claro, Sugar es el más lento y la mayor sorpresa es que Realm hasta le gana al OpenHelper (pueden ver los proyectos y si pillan que hice algo mal, por favor me avisan).

10 mil lecturas en mili segundos:

Realm Sugar OpenHelper
Nexus 5X API 23 (emulador) 21 1623 3
Nexus 5X API 22 (emulador) 31 2934 7
Sony Xperia C3 API 22 23 9594 6
Galaxy Note 3 Neo API 19 67 2101 8

Acá hay que aclarar una cosa, el OpenHelper es medio tramposo porque al leer no entrega modelos, sino que un Cursor. Para aclarar esto hay que tener un poco de contexto, antes Android ofrecía directamente adaptadores para listas que consumían cursores, que no fueron actualizados para la nueva RecyclerView optimizada en performance. Acá hay un proyecto en donde utilizo un Cursor para actualizar un Recycler Adapter, pero la tendencia y por eso menciono el adaptador, es a que se trabaje con modelos. En cambio, Sugar y Realm, devuelven una List<Pending>. Así que acá hay que leer los resultados con criterio individual, pero lo que sí queda claro es que Sugar nuevamente es el más lento.

Antes de cerrar quiero mencionar que he leído en los issues de Github de Sugar, que los log que tira son gran responsables de la performance, así que seré indulgente y esperaré a que lo arreglen pronto.

Conclusión

Realm no sólo tiene buena performance además tiene más funcionalidades. Sugar nos alcanza bien para proyectos chicos. El OpenHelper me deja la sensación de que es para personas old school