Recomendaciones sobre el diseño del esquema

Esta página contiene información sobre el diseño de esquemas de Bigtable. Antes de ti leer esta página, debes conocer la descripción general de Bigtable En esta página, se abordan los siguientes temas:

Conceptos generales

Diseñar un esquema de Bigtable es diferente de diseñar un esquema para una base de datos relacional. Un esquema de Bigtable se define por en lugar de usar un objeto o archivo de definición de esquema. Puedes agregar familias de columnas a una tabla cuando la creas o actualizas, pero los patrones de claves de filas y columnas se definen según los datos que escribes en la tabla.

En Bigtable, un esquema es un plano técnico o modelo de una tabla, que incluye la estructura de los siguientes componentes de la tabla:

  • clave(s) de fila
  • Familias de columnas, incluidas sus políticas de recolección de elementos no utilizados
  • Columnas

En Bigtable, el diseño del esquema se basa principalmente en las consultas, o de lectura que planeas enviar a la tabla. Dado que leer un rango de filas es la forma más rápida de leer tus datos de Bigtable, las recomendaciones de esta página están diseñadas para ayudarte a realizar optimizaciones para las operaciones de lectura de rangos de filas. En la mayoría de los casos, eso significa enviar una consulta basada en los prefijos de claves de fila.

Otra consideración es evitar los hotspots, para evitarlos, debes considerar los patrones de escritura y cómo puedes evitar el acceso a una clave pequeña espacio en poco tiempo.

Los siguientes conceptos generales se aplican al diseño de esquemas de Bigtable:

  • Bigtable es un almacén de clave-valor, no un almacén relacional. No admite uniones, y las transacciones solo se admiten dentro de una misma fila.
  • Cada tabla tiene solo un índice: la clave de fila. No hay índices secundarios. Cada clave de fila debe ser única.
  • Las filas se ordenan lexicográficamente por clave de fila, desde la mayor string de bytes a la menor. Las claves de fila se ordenan en el orden de bytes big-endian (a veces, llamado orden de bytes de red), el equivalente binario del orden alfabético.
  • Las familias de columnas no se almacenan en ningún orden específico.
  • Las columnas se agrupan por familia de columnas y se clasifican en orden lexicográfico dentro de la familia de columnas. Por ejemplo, en una familia de columnas llamada SysMonitor con calificadores de columna de ProcessName, User, %CPU, ID, Memory, DiskRead y Priority, Bigtable almacena las columnas en este orden:
SysMonitor
%CPU DiskRead ID Memoria Prioridad ProcessName Usuario
  • La intersección de una fila y una columna puede contener varias celdas con marca de tiempo. Cada celda contiene una versión única de los datos con marca de tiempo para esa fila y esa columna.
  • Las familias de columnas agregadas contienen celdas agregadas. Puedes crear de columnas que contengan solo celdas agregadas. Una agregación te permite combinar datos nuevos con datos que ya existen en la celda.
  • Todas las operaciones son atómicas a nivel de fila. Una operación afecta una fila entera o ninguna de la fila.
  • Lo ideal es que las operaciones de lectura y escritura se distribuyan de manera uniforme en el espacio de filas de la tabla.
  • Las tablas de Bigtable son dispersas. Una columna no ocupa ningún espacio en una fila que no use la columna.

Prácticas recomendadas

Un buen esquema genera un excelente rendimiento y escalabilidad, mientras que uno mal diseñado puede provocar un rendimiento deficiente del sistema. Cada caso de uso es diferente y requiere su propio diseño, pero las siguientes prácticas recomendadas se aplican a la mayoría de los casos de uso. Se mencionan excepciones.

En las siguientes secciones, se describen las prácticas recomendadas para el diseño de esquemas desde el nivel de tabla hasta el nivel de clave de fila:

Todos los elementos de tabla, en especial las claves de fila, deben diseñarse teniendo en cuenta las solicitudes de lectura planificadas. Verifica las cuotas y los límites para conocer los límites de tamaño recomendados y estrictos para todos los elementos de tabla.

Debido a que todas las tablas de una instancia se almacenan en la misma tablets, un diseño de esquema que da como resultado hotspots en una tabla pueden afectar la latencia de otras tablas de la misma instancia. Los hotspots se producen cuando se accede con frecuencia a una parte de la tabla en un período breve.

Tablas

Almacena conjuntos de datos con esquemas similares en la misma tabla, en lugar de en tablas separadas.

En otros sistemas de bases de datos, puedes elegir almacenar datos en varias tablas según el asunto y la cantidad de columnas. En Bigtable, sin embargo, suele ser mejor almacenar todos tus datos en una tabla. Puedes asignar un nombre de usuario prefijo de clave de fila para usar en cada conjunto de datos, de modo que Bigtable almacena los datos relacionados en un rango contiguo de filas que puedes consultar prefijo de clave de fila.

Bigtable tiene un límite de 1,000 tablas por instancia, pero te recomendamos que evites crear una gran cantidad de tablas por los siguientes motivos:

  • El envío de solicitudes a muchas tablas diferentes puede aumentar la sobrecarga de la conexión de backend, lo que aumenta la latencia final.
  • Crear más tablas no mejora el balanceo de cargas y puede aumentar la sobrecarga de administración.

Tal vez quieras una tabla separada para un caso de uso diferente que requiere un esquema diferente, pero no deberías usar tablas separadas para de datos no estructurados. Por ejemplo, no deberías crear una tabla nueva porque es un año nuevo o un cliente nuevo.

Familias de columnas

Coloca las columnas relacionadas en la misma familia de columnas. Cuando una fila contiene varios valores relacionados entre sí, se recomienda agrupar las columnas que contienen esos valores en la misma familia de columnas. Agrupa los datos lo más cerca posible, a fin de evitar la necesidad de diseñar filtros complejos y obtener solo la información que necesitas, pero no más, en tus solicitudes de lectura más frecuentes.

Crea hasta 100 familias de columnas por tabla. Crear más de 100 familias de columnas puede degradar el rendimiento.

Elige nombres cortos para tus familias de columnas. Los nombres se incluyen en los datos que se transfieren para cada solicitud.

Coloca columnas que tengan diferentes necesidades de retención de datos en diferentes familias de columnas. Esta práctica es importante si deseas limitar los costos de almacenamiento. Las políticas de recolección de elementos no utilizados se establecen en el nivel de familia de columnas, no en el nivel de columna. Por ejemplo, si solo necesitas conservar la versión más reciente de un un dato concreto, no lo almacenes en una familia de columnas que esté configurada para almacenar 1,000 versiones de otra cosa. De lo contrario, pagarás para almacenar 999 celdas de datos que no necesitas.

Columnas

Crea tantas columnas como necesites en la tabla. Bigtable están dispersas y no hay penalización de espacio para una columna que no se usa en una fila. Puedes tener millones de columnas en una tabla, siempre que ninguna fila exceda el límite máximo de 256 MB por fila.

Evita usar demasiadas columnas en una sola fila. Aunque una tabla puede tener millones de columnas, una fila no debe hacerlo. Algunos factores contribuyen a esto práctica recomendada:

  • Bigtable demora en procesar cada celda de una fila.
  • Cada celda agrega algo de sobrecarga a la cantidad de datos que se almacenan en tu tabla y que se envían por la red. Por ejemplo, si almacenas 1 KB (1,024 bytes) de datos, es mucho más eficiente almacenarlos en un en una sola celda, en lugar de repartir los datos entre 1,024 celdas que contienen 1 byte.

Si tu conjunto de datos requiere de forma lógica más columnas por fila de las que Bigtable puede procesar de manera eficiente, considera almacenar los datos como un protobuf en una sola columna.

De manera opcional, puedes tratar los calificadores de columnas como datos. Como debes almacenar un calificador de columna para cada columna, puedes ahorrar espacio nombrando la columna con un valor. A modo de ejemplo, considera una tabla que almacene datos sobre amistades en una familia de columnas Friends. Cada fila representa a una persona y todas sus amistades. Cada calificador de columna puede ser el ID de un amigo. Luego, el valor de cada columna de esa fila puede ser el círculo social en el que se encuentra el amigo. En este ejemplo, las filas podrían verse así:

Clave de fila Fred Gabriel Hiroshi Seo Yoon Jacob
José club de lectura trabajo tenis
Sofía trabajo school club de ajedrez

Comparar este esquema con un esquema para los mismos datos que no trata la columna calificadores que como datos y, en su lugar, tiene las mismas columnas en cada fila:

Clave de fila Amigo Palco
Jose#1 Fred club de lectura
Jose#2 Gabriel trabajo
Jose#3 Hiroshi tenis
Sofia#1 Hiroshi trabajo
Sofia#2 Seo Yoon school
Sofía n.o 3 Jacob club de ajedrez

El segundo diseño de esquema hace que la tabla crezca mucho más rápido.

Si usas calificadores de columna para almacenar datos, otorga nombres cortos pero significativos a las columnas. Este enfoque te permite reducir la cantidad de datos que se transfieren para cada solicitud. El tamaño máximo es de 16 KB.

Filas

Mantén el tamaño de todos los valores de una sola fila por debajo de los 100 MB. Asegúrate de que los datos de una sola fila no superen los 256 MB. Las filas que superen este límite pueden generar rendimiento reducido de la lectura.

Mantén toda la información de una entidad en una sola fila. En la mayoría de los casos de uso, evita almacenar datos que necesites leer de forma atómica o todos a la vez, en más de una fila, a fin de evitar incoherencias. Por ejemplo, si actualizas dos filas de una tabla, es posible que una fila se actualice correctamente y la otra actualización falle. Asegúrate de que tu esquema no necesite que se actualice más de una fila a la vez para que los datos relacionados sean precisos. Esta práctica garantiza que si parte de una solicitud de escritura falla o se debe volver a enviar, esa información no quedará incompleta de forma temporal.

Excepción: Si mantener una entidad en una sola fila genera filas de cientos de MB, debes dividir los datos entre varias filas.

Almacena entidades relacionadas en filas adyacentes para que las lecturas sean más eficientes.

celdas

No almacenes más de 10 MB de datos en un solo celular. Recuerda que una celda son los datos almacenados para una fila y una columna determinadas con una marca de tiempo única, y que se pueden almacenar varias celdas en la intersección de esa fila y columna. La cantidad de celdas retenidas en una columna se rige por la política de recolección de elementos no utilizados que estableces para la familia de columnas que contiene la columna.

Usa celdas de agregación para almacenar y actualizar datos agregados. Si solo te interesa el valor agregado de los eventos de una entidad, como la suma mensual de las ventas por empleado en una tienda minorista, puedes usar los agregados. Para ver más consulta Valores agregados en el momento de la escritura.

clave(s) de fila

Diseña tu clave de fila según las consultas que usarás para recuperar los datos. Las claves de fila bien diseñadas logran el mejor rendimiento de Bigtable. Las consultas de Bigtable más eficientes recuperan los datos mediante una de las siguientes opciones:

  • Clave de fila
  • Prefijo de la clave de fila
  • Rango de filas definido por las claves de fila inicial y final

Otros tipos de consultas activan un análisis completo de la tabla, lo que es mucho menos eficiente. Si eliges la clave de fila correcta, te ahorrarás un proceso de migración de datos agotador en el futuro

Usa claves de fila cortas. Una clave de fila debe ser de 4 KB o menos. Las claves de fila largas toman espacio de memoria y almacenamiento adicionales, y aumentar el tiempo necesario para obtener respuestas del servidor de Bigtable.

Almacena varios valores delimitados en cada clave de fila. A menudo, es útil que incluyas varios identificadores en tu clave de fila, debido a que la mejor forma de realizar consultas eficaces en Bigtable es a través de la clave de fila. Es especialmente importante comprender en profundidad cómo usas tus datos cuando tu clave de fila incluye varios valores.

Los segmentos de clave de fila suelen estar separados por un delimitador, como un carácter de hash, dos puntos o barra. El primer segmento, o conjunto de segmentos contiguos, es la clave de fila prefijo y el último segmento o conjunto de segmentos contiguos es la clave de fila .

Clave de fila de muestra

Los prefijos de clave de fila bien planificados te permiten aprovechar el orden de clasificación de Bigtable para almacenar datos relacionados en filas contiguas. El almacenamiento de datos relacionados en filas contiguas te permite acceder a datos relacionados como un rango de filas, en lugar de ejecutar análisis ineficientes de las tablas.

Si tus datos incluyen números enteros que deseas almacenar u ordenar de forma numérica, rellena los números enteros con ceros a la izquierda. Bigtable almacena los datos lexicográficamente. Por ejemplo, lexicográficamente, 3 > 20, pero 20 > 03. Rellenar el 3 con un cero inicial garantiza que los números se ordenen de forma numérica. Esta táctica es importante para las marcas de tiempo en las que se usan consultas basadas en rangos.

Es importante crear una clave de fila que permita recuperar un rango de filas bien definido. De lo contrario, tu consulta requiere un análisis de la tabla, que es mucho más lento que recuperar filas específicas.

Por ejemplo, si tu aplicación realiza un seguimiento de los datos del dispositivo móvil, puedes tener una clave de fila que contenga el tipo de dispositivo, el ID del dispositivo y el día en que se registran los datos. Las claves de fila para estos datos podrían verse así:

        phone#4c410523#20200501
        phone#4c410523#20200502
        tablet#a0b81f74#20200501
        tablet#a0b81f74#20200502

Este diseño de clave de fila te permite recuperar datos con una sola solicitud para lo siguiente:

  • Un tipo de dispositivo
  • Una combinación del tipo de dispositivo y el ID del dispositivo

Este diseño de clave de fila no sería óptimo si deseas recuperar todos los datos de un día determinado. Debido a que el día se almacena en el tercer segmento o en el sufijo de la clave de fila, no puedes solicitar un rango de filas según el sufijo o un segmento medio de la clave de fila. En su lugar, debes enviar una solicitud de lectura con un filtro que analice toda la tabla en busca del valor del día.

Usa valores de string legibles en tus claves de fila siempre que sea posible. Esta práctica facilita el uso de la herramienta Key Visualizer para solucionar problemas con Bigtable.

A menudo, debes diseñar claves de fila que comiencen con un valor común y terminen en un valor detallado. Por ejemplo, si tu clave de fila incluye un continente, un país y una ciudad, puedes crear claves de filas que se vean de la siguiente manera para que primero ordenen de forma automática por valores con cardinalidad más baja:

        asia#india#bangalore
        asia#india#mumbai
        asia#japan#osaka
        asia#japan#sapporo
        southamerica#bolivia#cochabamba
        southamerica#bolivia#lapaz
        southamerica#chile#santiago
        southamerica#chile#temuco

Claves de fila que debes evitar

Algunos tipos de claves de fila pueden dificultar la consulta de tus datos y algunos dan como resultado un rendimiento deficiente. En esta sección, se describen algunos tipos de claves de fila que debes evitar usar en Bigtable.

Claves de fila que comienzan con una marca de tiempo. Este patrón hace que las escrituras secuenciales se envíen a un solo nodo, creando un hotspot. Si colocas una marca de tiempo en una clave de fila y la precedes con un valor de alta cardinalidad, como un ID de usuario para evitar hotspots.

Claves de fila que provocan que los datos relacionados no se agrupen. Evita las claves de fila que hacen que los datos relacionados se almacenen en rangos de filas no contiguos, ya que leerlos juntos es ineficiente.

ID numéricos secuenciales. Imagina que tu sistema asigna un ID numérico a cada uno de los usuarios de tu aplicación. Es posible que te parezca una buena idea usar el ID numérico del usuario como clave de fila en tu tabla. Sin embargo, debido a que es más probable que los usuarios nuevos sean usuarios activos, es posible que este enfoque envíe la mayor parte de tu tráfico a una pequeña cantidad de nodos.

Un enfoque más seguro es usar una versión invertida del ID numérico del usuario, que distribuye el tráfico de manera más uniforme en todos los nodos de tu tabla de Bigtable.

Identificadores que se actualizan con frecuencia. Evita usar una sola clave de fila para identificar un valor que debe actualizarse con frecuencia. Por ejemplo, si almacenas datos de uso para una cantidad de dispositivos una vez por segundo, no uses una clave de fila única para en cada dispositivo compuesto por el ID de dispositivo y la métrica que se almacena, como como 4c410523#memusage y actualizar la fila varias veces. Este tipo de operación sobrecarga la tablet que almacena la fila de uso frecuente. También puede causar que una fila exceda su límite de tamaño, porque los valores anteriores de una columna ocupan espacio hasta que las celdas se quitan durante la recolección de elementos no utilizados.

En su lugar, almacena cada lectura nueva en una fila nueva. En el ejemplo de uso de memoria, cada clave de fila puede contener el ID de dispositivo, el tipo de métrica y una marca de tiempo, de modo que las claves de fila sean similares a 4c410523#memusage#1423523569918. Esta estrategia es eficiente porque, en Bigtable, crear una fila nueva no lleva más tiempo que crear una celda nueva. Además, esta estrategia te permite leer datos de un período específico calculando las horas de inicio las claves de finalización.

Para los valores que cambian con frecuencia, como un contador que se actualiza cientos de veces por minuto, la mejor opción es mantener los datos en la memoria, en la capa de la aplicación, y escribir nuevas filas en Bigtable periódicamente.

Valores con hash. Agregar hash a una clave de fila te impide aprovechar el orden natural de Bigtable, lo que hace imposible almacenar las filas de manera óptima para realizar consultas. Por el mismo motivo, agregar hash a los valores dificulta el uso de la herramienta Key Visualizer para solucionar problemas con Bigtable. Usa valores legibles en lugar de valores con hash.

Valores expresados como bytes sin procesar, en lugar de strings legibles. Los bytes sin procesar son adecuados para los valores de columnas. Sin embargo, para la legibilidad y la solución de problemas, es mejor usar valores de string en las claves de fila.

Casos de uso especiales

Es posible que tengas un conjunto de datos único que requiera una consideración especial cuando diseñas un esquema para almacenarlo en Bigtable. En esta sección, se describen algunos tipos de datos de Bigtable, pero no todos, y algunas tácticas sugeridas para almacenarlos de la manera más óptima.

Datos basados en el tiempo

Incluye una marca de tiempo como parte de la clave de fila si a menudo recuperas datos en función del momento en que se registraron.

Por ejemplo, es posible que tu aplicación registre datos relacionados con el rendimiento, como el uso de la CPU y la memoria, una vez por segundo para muchas máquinas. Tu clave de fila para estos datos podría combinar un identificador para la máquina con una marca de tiempo para los datos (por ejemplo, machine_4223421#1425330757685). Ten en cuenta que las claves de fila se ordenan de manera lexicográfica.

No uses una marca de tiempo sola o al comienzo de una clave de fila, ya que esto hará que las escrituras secuenciales se envíen a un solo nodo y creen un hotspot. En este caso, debes considerar los patrones de escritura, además de las operaciones o patrones.

Si por lo general recuperas primero los registros más recientes, puedes usar una marca de tiempo invertida en la clave de fila cuando le quites la marca de tiempo del valor máximo de tu lenguaje de programación para números enteros largos (en Java, java.lang.Long.MAX_VALUE). Con una marca de tiempo invertida, los registros se ordenarán del más reciente al menos reciente.

Para obtener información específica sobre cómo trabajar con datos de series temporales, consulta Esquema diseñar para datos de series temporales.

Multiusuario

Los prefijos de clave de fila proporcionan una solución escalable para los casos prácticos de “instancias múltiples”, lo que ocurre cuando almacenas datos similares, con el uso del mismo modelo de datos, en nombre de varios clientes. El uso de una tabla para todas las instancias es la forma más eficaz de almacenar y acceder a los datos de varias instancias.

Por ejemplo, supongamos que almacenas y realizas un seguimiento de los historiales de compra en nombre de muchas empresas. Puedes usar tu ID único para cada empresa como prefijo de clave de fila. Todos los datos de un usuario se almacenan en filas contiguas en la misma tabla, y puedes buscarlos o filtrarlos mediante el prefijo de la clave de fila. Luego, cuando una empresa ya no sea tu cliente y necesites borrar los datos del historial de compras que almacenabas para ellos, puedes descartar el rango de filas que usan el prefijo de clave de fila de ese cliente.

Por ejemplo, si almacenas los datos de dispositivos móviles para los clientes altostrat y examplepetstore, puedes crear claves de filas como las que se muestran a continuación: Luego, si altostrat ya no es tu cliente, descartas todas las filas con el prefijo de clave de fila altostrat.

        altostrat#phone#4c410523#20190501
        altostrat#phone#4c410523#20190502
        altostrat#tablet#a0b41f74#20190501
        examplepetstore#phone#4c410523#20190502
        examplepetstore#tablet#a6b81f79#20190501
        examplepetstore#tablet#a0b81f79#20190502

En cambio, si almacenas datos en nombre de cada empresa en su propia tabla, puedes experimentar problemas de escalabilidad y rendimiento. También es muy probable que, sin darte cuenta, alcances el límite de 1,000 tablas por instancia de Bigtable. Después de que una instancia alcanza este límite, Bigtable evita que crees más tablas en la instancia.

Privacidad

A menos que tu caso de uso lo requiera, evita usar información de identificación personal (PII) o datos de usuario en claves de fila o IDs de familia de columnas. Los valores de las claves de fila y las familias de columnas son datos del cliente y del servicio, y las aplicaciones que los usan, como la encriptación o el registro, pueden exponerlos accidentalmente a los usuarios que no deberían tener acceso a datos privados.

Para obtener más información sobre cómo se manejan los datos del servicio, consulta la página Privacidad Aviso.

Nombres de dominio

Puedes almacenar nombres de dominio como datos de Bigtable.

Amplia gama de nombres de dominio

Si almacenas datos sobre entidades que pueden representarse como nombres de dominio, considera usar un nombre de dominio inverso (por ejemplo, com.company.product) como la clave de fila. El uso de un nombre de dominio inverso es ideal si los datos de cada fila tienden a superponerse con las filas adyacentes. En este caso, en Bigtable se pueden comprimir tus datos de manera más eficiente.

En cambio, los nombres de dominio estándar que no se revierten pueden hacer que las filas se ordenen de tal manera que los datos relacionados no se agrupen en un solo lugar, lo que puede generar una compresión menos eficiente y lecturas menos eficientes.

Este enfoque funciona mejor cuando tus datos se distribuyen a través de muchos nombres de dominio inversos diferentes.

Para ilustrar este punto, considera los siguientes nombres de dominio, que Bigtable ordena de forma automática en orden lexicográfico:

      drive.google.com
      en.wikipedia.org
      maps.google.com

Esto no es recomendable para el caso de uso en el que deseas consultar todas las filas de google.com. Por el contrario, considera las mismas filas en las que se revirtieron los nombres de dominio:

      com.google.drive
      com.google.maps
      org.wikipedia.en

En el segundo ejemplo, las filas relacionadas se ordenan de forma automática de manera tal que facilita su recuperación como un rango de filas.

Pocos nombres de dominio

Si esperas almacenar una gran cantidad de datos para una pequeña cantidad de nombres de dominio o solo uno, considera otros valores para tu clave de fila. De lo contrario, podrías enviar escrituras a un solo nodo en tu clúster y generar hotspots, o tus filas podrían crecer demasiado.

Consultas cambiantes o inciertas

Si no siempre ejecutas las mismas consultas en tus datos o no estás seguro de qué consultas harás, una opción es almacenar todos los datos de una fila en una columna en lugar de varias columnas. Con este enfoque, usas un formato que facilita la extracción de los valores individuales más adelante, como el formato binario del búfer de protocolo o un archivo JSON.

La clave de fila aún está diseñada con cuidado para garantizar que puedas recuperar los datos que necesitas, pero cada fila suele tener solo una columna que contiene todos los datos de la fila en un solo protobuf.

Almacenar datos como un mensaje protobuf en una sola columna en lugar de distribuirlos en varias columnas tiene ventajas y desventajas. Estas son algunas ventajas:

  • Los datos ocupan menos espacio, por lo que te cuesta menos almacenarlos.
  • Puedes mantener una cierta flexibilidad, ya que no te comprometes con familias de columnas ni calificadores de columnas.
  • La aplicación de lectura no necesita "saber" cuál es el esquema de tu tabla.

Estas son algunas desventajas:

  • Debes deserializar los mensajes protobuf después de que se leen desde Bigtable.
  • Se pierde la opción de consultar los datos en mensajes protobuf mediante filtros.
  • No puedes usar BigQuery para ejecutar consultas federadas en campos dentro de mensajes protobuf después de leerlos desde Bigtable.

¿Qué sigue?