Ventajas y desventajas de usar máscaras de bits en la base de datos

22

No hace mucho, hablé con mi colega y él definitivamente estaba en contra del uso de máscaras de bits porque es difícil entender todos los valores almacenados en la base de datos. En mi opinión, no siempre es una mala idea usarlos, por ejemplo, para determinar los roles del usuario actual. De lo contrario, debe almacenarlo en una tabla separada, lo que provocará una UNIÓN más. ¿Puedes decirme si estoy equivocado? ¿Algún otro efecto secundario, ventajas / desventajas del uso de máscaras de bits?

Alex Ovechkin
fuente
2
Puede tener más sentido que la base de datos cree máscaras de bits internamente y le presente los bits como columnas separadas. Sus requisitos pueden cambiar.
Simon Richter
1
Si no usa uniones, no está usando su base de datos relacional de la manera prevista.
Pieter B

Respuestas:

38

Trabajo con una aplicación que usa máscaras de bits para almacenar asignaciones de roles de usuario. Es un dolor en el trasero. Si esto me hace parcial, culpable como acusado.

Si ya está utilizando una base de datos relacional, es un antipatrón que viola la mayoría de la teoría relacional y todas las reglas de normalización. Cuando crea su propio almacenamiento de datos, puede que no sea una mala idea.

Existe la posibilidad de unir demasiadas tablas, pero las bases de datos relacionales están diseñadas para manejar esto. Muchos tienen características adicionales si el rendimiento se convierte en un problema: índices, vistas indexadas, etc. Incluso si los valores que está buscando no cambian con mucha frecuencia, lo cual es una ventaja para Bitmask, lo importante es tener que administrar la indexación. bastante fácil en la base de datos.

Aunque la base de datos hace un buen trabajo al agregar datos, pueden volverse lentos cuando comienza a introducir cosas como fórmulas complejas o funciones escalares en conjuntos de datos. Puede hacer el bit a bit en su aplicación, pero si todo lo que está haciendo es obtener datos relacionados (buscar los roles de un usuario), no está aprovechando lo que su almacenamiento de datos hace mejor.

Mi último argumento en contra sería la simplicidad para otros desarrolladores. Tienes usuarios, roles y tareas. Es un conjunto de relaciones de muchos a muchos (porque hay más de una relación) que es tan común que debería ser fácil de administrar. Es solo cosas CRUDAS.

JeffO
fuente
8
Una base de datos relacional es el peor lugar para una máscara de bits. Los costos de almacenamiento ya no son tan malos que unas pocas uniones y una mesa adicional deberían romperlo. Ciertamente hace que todo sea más difícil de razonar. Almacenar los permisos como bits (1/0) en la base de datos en su propia tabla y representarlos en código con solo banderas. Parece bastante apropiado y factible. Los desarrolladores obtienen banderas simples y los dbas tienen tablas normalizadas. Todos están felices.
Mike McMahon
3
De acuerdo, solía admitir una aplicación que usaba máscaras de bits para roles de usuario y privilegios en su base de datos. Fue una pesadilla. Usando un int 32 bit, nos quedamos sin bits, por lo que alguien tuvo la gran idea de agregar más máscaras de bits, y luego con superposiciones, por lo que el bit 4 en una columna significaba el bit 8 en esta otra columna, y se desincronizaron. Sí, sí, sí. Fue difícil indexar porque los índices almacenan valores de columna discretos, no los bits individuales en ellos, por lo que no puede buscar filas where some_bit_mask & 12 > 0sin un escaneo fila por fila.
Brandon
Al final del día, una relación muchos-a-muchos user_role_mapo user_priv_mapmesa habría sido suficiente.
Brandon
@MikeMcMahon, ¿podría profundizar en el diseño de la tabla y cómo debería mapearlo en código para lograr el resultado del que está hablando?
Alex Ovechkin
2
@ usr - Nunca digas nunca. Claro que puede usar máscaras de bits, pero no las usaría en una aplicación que usa una base de datos relacional. Probablemente hay algunos casos extremos cuando se trata de datos heredados o una súper necesidad de velocidad.
JeffO
24

Ya ha nombrado los pros y los contras relevantes:

  • Los campos de bits ahorran espacio.
  • Almacenan datos en el registro mismo, por lo que no necesita unir para encontrarlos. (Pero los campos de marca individuales en el registro harían lo mismo).
  • Son poco legibles si desea trabajar productivamente con salida SQL sin formato.

Decidir qué hacer requiere más información:

  • ¿Qué tan escaso es el espacio en disco para su caso de uso?
  • ¿Realmente lees los roles de los usuarios con tanta frecuencia que el momento de UNIRSE a ellos es un cuello de botella?
  • ¿ Va a leer la salida SQL y tomar decisiones basadas en eso, o es un registro de base de datos ilegible inmaterial, al igual que el hecho de que el código de máquina de su sistema es ilegible?

Entonces, lo que tiene que hacer es reunir los factores de riesgo y luego ponderarlos , para ver si los profesionales superan a los contras.

Kilian Foth
fuente
Gracias por su respuesta, totalmente de acuerdo con sus pensamientos, pero en general, ¿es este antipatrón o no? ¿Y usas máscaras en tus proyectos?
Alex Ovechkin
12
@Alex No existe una "mejor práctica" que pueda decidir qué hacer en su caso. Si tiene muy poco espacio, la mejor práctica es usar campos de bits. Si desea utilizar la salida de SQL en los informes para el CEO, la mejor práctica es usar nombres que hablen. Pero usted es el único que conoce estas circunstancias, por lo tanto, la comunidad no puede darle una receta que siempre sea válida.
Kilian Foth
Tomando el argumento del espacio como un "dame". La cuestión de si usar una máscara de bits se basa o no en si infiere algún beneficio por encima de esto.
Robbie Dee
Además, ¿TODO necesita procesar la información en la base de datos, o siempre se lee en una aplicación antes de usarla?
Ian
1
"¿Va a leer la salida SQL y tomar decisiones basadas en eso, o es un registro de base de datos ilegible inmaterial, al igual que el hecho de que el código de máquina de su sistema es ilegible?" Supongo que no puedo hablar por todos los desarrolladores, pero cuando estoy desarrollando, es extremadamente común para mí comenzar a seleccionar datos de la base de datos para comprender o verificar algo. Por lo tanto, diría que , por lo general , la respuesta a esto es: "Sí, alguien lo hará".
jpmc26
18

Si está realmente, realmente , realmente limitado para el espacio en disco, entonces podría considerar mapas de bits para permisos de usuario. Si el rendimiento es tu preocupación, entonces olvídate de ellos por completo, porque separarlos en realidad será más lento. No puede indexar un campo de mapa de bits de manera significativa, lo que resulta en escaneos de la tabla de la base de datos, que [casi] siempre son un factor decisivo para el rendimiento.

A menos que sea Amazon o Netflix, la cantidad de datos involucrados en los permisos de los usuarios será insignificante en comparación con todo lo demás que tiene.

Cualquier DBMS serio puede manejar esa "unión extra" sin siquiera parpadear.

Phill W.
fuente
77
+1: Las buenas bases de datos relacionales son desarrolladas por personas que son muy, muy, muy buenas en lo que hacen. Cualquier persona en el nivel de necesidad de exprimir el último bit de rendimiento que podría obtener al usar campos de bits no necesitaría hacer la pregunta. Modele los datos, luego encuentre las partes que no funcionan.
Blrfl
Tener la unión hará que el código de la aplicación sea más complejo, por lo que todo se reduce a DONDE se procesan los roles.
Ian
44
@Ian tener la unión no parece más complejo que la necesidad de saber cómo descifrar los permisos de máscara de bits.
Brad
@Brad, piense en una enumeración que es un conjunto de indicadores en C #, con su valor almacenado "tal cual" en la base de datos, el frío de C # no puede ser más simple. Si se usa una combinación, entonces el código C # tiene que hacer frente a una relación de "1 a muchos".
Ian
También debo agregar que si tiene varias columnas booleanas en una tabla, la mayoría de las bases de datos descubrirán cómo aplastarlas en el menor espacio posible y se encargarán de los cambios de bits por usted.
Blrfl
8

Cuando el almacenamiento era costoso, la bendición con las máscaras de bits era que ahorraban espacio. En los días de Big Data, este no es el problema que alguna vez fue.

Tomando el ejemplo que usted cita: tener roles almacenados como una máscara de bits sería una especie de olor a código desde el punto de vista del diseño de la base de datos, ya que violaría la primera forma normal . En este sentido, son un antipatrón.

Dicho todo esto, no tiene que ser uno ni el otro. Puede almacenar los datos como una máscara de bits y luego tener una vista que pueda extraer los roles de los usuarios sobre la marcha. También tendría la ventaja de comprobar de un vistazo qué usuarios tenían los mismos roles.

Robbie Dee
fuente
2

La única ventaja de usar máscaras de bits es si el significado de los campos de bits no es estático. Las tablas relacionales solo funcionan bien si sabe de antemano qué es cada campo en un registro: CREATE TABLEdespués de todo, debe identificar los campos en la declaración DDL.

Si el significado de cada campo de bit es configurable en tiempo de ejecución, o si no se conoce de antemano, entonces podría tener sentido almacenar booleanos como un campo de bit. Incluso entonces, es posible definir una tabla con los campos arbitrarios: field_1, field_2, etc. Esto le da un diseño relacional más limpio, aunque todavía no es ideal. Si esto es preferencial a un campo de bits es en gran medida una cuestión de opinión, ya que ninguna de las soluciones es ideal.

Si sabe lo que representan los bits durante el desarrollo, cree campos para cada bit y asígneles nombres significativos .

Solo tenga cuidado con el efecto de plataforma interna . Si terminas definiendo campos arbitrarios pero bien escritos, eso es una cosa, pero si vas mucho más allá de eso, reinventarás una base de datos relacional ... dentro de una base de datos relacional.


fuente
2

Soy ambivalente sobre las máscaras de bits. Me parece que la mayoría de sus detractores no entienden binario y hexadecimal. Para mayor claridad, usa buenos mnemónicos.

Una ventaja no mencionada anteriormente es la capacidad de agregar un nuevo significado a las máscaras de bits sin la adición de una nueva columna que puede llevar mucho tiempo. Nuestros diseñadores de db (que me precedieron) los tienen en una tabla que ahora obtiene 5 millones de nuevos registros diarios. Agregar una nueva columna para representar un nuevo comportamiento llevaría mucho tiempo, mientras que definir un nuevo bit (hemos consumido 33 de 64) no requiere la reconstrucción de la tabla.

No, las máscaras de bits no se pueden indexar, pero crear 33 índices sería ridículo y ralentizaría las inserciones en un rastreo. Las búsquedas de tablas utilizan los índices de "propietarios" de fechas y registros, por lo tanto, los índices en esta máscara de bits, si es posible, nunca se utilizarían.

GB
fuente
Es un caso interesante. Supongo que podría lograr lo mismo de una manera kosher y explícita, definiendo columnas "sobrantes" en la tabla y luego usándolas según sea necesario. A continuación, puede al menos indexar estas columnas de forma selectiva, si decide hacerlo.
Steve
1

Si el objetivo es solo ahorrar algo de espacio en disco, creo que es una mala idea:

  • mira el costo del GB hoy,
  • compárelo con el costo del tiempo de quienes escriben informes y consultas y tienen que averiguar qué hay en el campo y cómo abordar un bit específico, la comparación de costo / beneficio podría terminar en el lado equivocado.
  • Si está trabajando con una base de datos SQL, las operaciones de acceso de bits adicionales requeridas en muchas consultas también pueden consumir más tiempo de cómputo del necesario

Sin embargo, hay algunos casos que pueden justificar el uso de campos de bits:

  • si sus bits representan un conjunto complejo de indicadores que siempre maneja en conjunto,
  • aún más si necesita aplicar algunos algoritmos de coincidencia de patrones en estos conjuntos,
  • y especialmente si estos datos no se encuentran entre los criterios de selección más utilizados.
Christophe
fuente