Database sharding (I)

El problema

El producto era estupendo. Fué una idea genial, traída de los Estados Unidos a España en el momento de mercado adecuado. La estrategia IT consistía en construir el producto en casa. Era una buena estrategia porque le permitía mayor versatilidad que otros productos comerciales, que no hacían lo que el negocio requería, y además el coste era menor porque lo se lo hacía un amigo que "sabía mucho de informática".

Y todo fue bien al principio, hasta que la cosa empezó a coger velocidad. Empezaron a entrar muchos usuarios, pero muchos muchos, y entonces empezaron los problemas: cuelgues a horas punta, retrasos en las nuevas funcionalidades porque era difícil añadirlas, horas extra sin pagar, noches interminables, usuarios enfadados, jefes cabreados: el software hecho en casa no estaba a la altura del producto, y el negocio corría peligro.

(La historia podría parecer aterradora, pero es lamentablemente muy frecuente).

Las causas

Las causas de toda esta sintomatología eran muy variopintas: la falta de destreza del "amigo que sabía mucho de informática", las prisas, la presión por hacer las cosas rápido y mal. Pero quizá la más grave, y de la que hablaré hoy, consistía en un error de diseño: la base de datos era una sola, muy gorda, y se convertía en un cuello de botella insalvable.

Y este tipo de errores de diseño, como todos los errores de diseño, se corrigen sólo a base de dinero y de esfuerzo adicional. De mucho dinero y mucho esfuerzo. ¡Ay, si hubiesen diseñado bien su sistema al principio!

Imaginémonos que tenemos un porrón de usuarios, donde "porrón" es un número muy grande. Imaginémonos también que cada usuario hace "tropecientas" compras, y que queremos almacenar estas compras para luego analizarlas. En total tenemos "un porrón" multiplicado por "tropecientas" compras: un "mogollón", vamos.

Aquél cliente guardaba el "mogollón" de entradas en una única base de datos, que fue creciendo conforme el producto iba teniendo éxito. Llegó un momento que la base de datos creció tanto que las consultas sobre el "mogollón" de entradas se hacían muy lentas, y hacían a todo el sistema muy lento.

Divide y vencerás

Hay muchas técnicas para diseñar bases de datos. Hay algunas con formulación matemática y todo. Pero son muy aburridas. Hay una técnica, sin embargo, que es fácil de explicar y, creo, de entender: es la de "database sharding") o "particionamiento de bases de datos" (creo que se traduce así).

La técnica es tan sencilla de contar que es prácticamente una tontería. Es en una variación del famoso algoritmo de 'divide y vencerás', y consiste en trocear la base de datos "grande" en otras más pequeñitas, llamadas "particiones" o "shards". Así de sencillo, y de complicado.

El cliente podría haber dividido la base de datos en otras más pequeñas, lo más independientes entre sí como fuera posible. Por ejemplo, aquél cliente podría haber separado los usuarios por zonas geográficas, o por la primera letra de su apellido, por ejemplo, separando la base de datos "gorda" inicial en otras más pequeñas (todos los clientes de España, todos los de Italia, todos los de Alemania, o todos los que empiezan por 'A', todos los que empiezan por 'B', etcétera).

Consultar la base de datos entonces hubiese sido un poco más complicado. Tendría que haber "dividido" también las consultas iniciales en otras más pequeñas, y luego "juntar" los resultados (esta técnica de "dividir" y "juntar" se llama, en inglés, "fork & join").

Por ejemplo, la consulta inicial "usuarios que han comprado un abrigo verde" se separa en consultas más pequeñas: se consulta "usuarios de España que han comprado un abrigo verde" en la base de datos de "España", se consulta "usuarios de Italia que han comprado un abrigo verde" en la base de datos de "Italia", etcétera, y luego se "juntan" para dar un resultado global.

Escalabilidad horizontal: ahorrando pasta

La principal ventaja de separar la base de datos inicial, muy grande, en otras más pequeñas es que estas otras más pequeñas se pueden instalar en diferentes servidores, pudiendo escalar el sistema horizontalmente, esto es, asignar más ordenadores diferentes, separados físicamente entre sí.

O no, quizá nos convenga agrupar bases de datos que se usan poco (la de "Uganda" y la de "Albania", por poner un ejemplo) en el mismo ordenador pequeño, y asignar un ordenador más grande a aquellas "particiones" que más trajín tienen.

Si el diseño está bien hecho quizá podamos "reparticionar" las particiones. Si vemos, por ejemplo, que la partición de España tiene mucha carga de trabajo quizá podamos separarla en una partición para Madrid, otra para Barcelona y otra para el resto.

Resumen. Otro día más.

En resumen, las ventajas del particionamiento de base de datos son importantes y pueden permitirnos ahorranos pasta y ofrecer un mejor servicio. Hay que tenerlas en cuenta al principio, en la fase de diseño, ya que adoptarlas en medio del partido puede ser costoso.

Otro día cuento más batallitas: quién usa sharding por ahí adelante (Flickr, Google, Twitter), qué desventajas tiene, qué herramientas hay y qué criterios son mejores para particionar.