2012-08-02 10 views

Respuesta

7

La respuesta a su pregunta es "no". Los campos de bits sacrifican la integridad relacional, por la sencilla razón de que tiene entidades en la base de datos que no tienen las tablas correspondientes.

Dicho esto, muchas bases de datos ofrecen soporte para esto, generalmente a través de un tipo de datos "bit". Mysql tiene un soporte aún más fuerte, con el tipo de datos "establecer".

El problema principal es que no sabe nada sobre los elementos del conjunto: cuál es el nombre completo, cuándo se agregó a la base de datos, etc. (Las ediciones envuelven parte del problema de nombres). Además, el tamaño del conjunto es limitado. Puede tener un ejemplo donde las cosas son limitadas. Sin embargo, el ejemplo de Matt enfatiza el problema aquí. Puede tener una lista de los continentes visitados. Sin embargo, cuando cambia a los países visitados, el enfoque es necesariamente bastante diferente, porque la cantidad de países ya no cabe en una sola "palabra". ¿Le gustaría que su sistema trate los continentes de manera muy diferente a los países a este respecto? ¿Desea que sus decisiones de diseño estén restringidas por el límite de 32 o 64 bits en una palabra de computadora?

Y, por último, parece que la proliferación de tablas es un problema. La proliferación de tablas es en realidad una solución. Todos los datos sobre las entidades se almacenan en tablas, en lugar de distribuirse a través del sistema. Puede mantener información sobre las instancias de la entidad, como cuándo se creó la instancia, cómo podría haber cambiado con el tiempo, y así sucesivamente. Es probable que se use una entidad para "continentes" siempre que alguien quiera un continente.

Considere lo que sucede en un sistema en el que dos desarrolladores diferentes deciden desarrollar sus propias máscaras de bits para los continentes, pero colocan los continentes en un orden diferente.Con una base de datos relacional bien diseñada (lo que significa que las relaciones de claves externas se declaran explícitamente en la definición de la tabla), dicha confusión no podría surgir.

+1

Estoy de acuerdo. Me gustaría añadir que corre el riesgo de perder la claridad de la consulta con el enfoque de campo bit a bit "hágalo usted mismo". La claridad y la simplicidad son realmente importantes en sistemas no triviales. – smv

9

Para una relación uno a muchos, donde los "muchos" tienen un número pequeño de valores conocidos, las relaciones pueden almacenarse como máscaras de bits en la tabla padre como un entero, reemplazando la necesidad de una tabla adicional.

Digamos que tenemos una tabla Persona y nos gustaría saber cuántos continentes ha visitado una persona. Comenzaríamos asignando a cada Continente un valor de bit "ortogonal". En C#, una enumeración es una buena opción para esto:

[Flags] 
public enum JobAdvertisingRegion 
{ 
    NorthAmerica = 1,    // or 1 << 0 
    SouthAmerica = 2,    // 1 << 1 
    Europe = 4,     // 1 << 2 
    Asia = 8,      // 1 << 3 
    Africa = = 16,     // 1 << 4 
    Australia = 32,    // 1 << 5 
    Anarctica = 64     // 1 << 6 
} 

La tabla personas podrían entonces simplemente tener una columna int llamados Contintents. Para indicar que una persona ha visitado Europa y Asia:

UPDATE Persons SET Continents = (4 + 8) WHERE Id = whatever 

a buscar a las personas que han visitado la Antártida, utilizamos las matemáticas a nivel de bits:

SELECT * FROM Persons WHERE Continents & 64 = 64 

a buscar a las personas que han visitado tanto en África y Asia :

SELECT * FROM Persons WHERE Continents & (16 + 8) = (16 + 8) 

de búsqueda de personas que han visitado Australia o América del Sur:

SELECT * FROM Persons WHERE Continents & (32 + 2) != 0 

Una desventaja es que, mientras que las columnas enteras son indexables en SQL, sus componentes de bits no lo son. Algunas optimizaciones para evitar esto, para las consultas anteriores:

SELECT * FROM Persons WHERE Continents & 64 = 64 AND Continents >= 64 

SELECT * FROM Persons WHERE Continents & (16 + 8) = (16 + 8) AND Continents >= (16 + 8) 

SELECT * FROM Persons WHERE Continents & (32 + 2) != 0 AND Continents >= 2 
+1

Y luego con el tiempo que desea generar un buen informe utilizando una herramienta de informes dB de relación, pero los números no van a tener un significado para el usuario final del informe, por lo que necesita un mapeo de los números a la continentes y luego querrás saber cuántas personas visitaron 3 o más continentes y necesitarás introducir una función u otra asignación para que la herramienta de informes pueda recogerla. ¿Por qué hacer esto a ti mismo? Si se usa una base de datos relacional, las estructuras relacionales terminan siendo muy útiles. – Glenn

+7

-1 Viola 1NF, se optimiza para el espacio en la era de las unidades de terabyte baratas, no escala a más de 64 regiones, usa el patrón matemático binario contra el patrón – Andomar

1

Bueno, voy a ir en contra de la opinión (actualmente) popular aquí simplemente indicando algunos hechos

  • SQL y el modelo relacional son no la misma cosa.
  • El modelo relacional (teoría) funciona con variables relacionales, llamadas relvars.
  • Las bases de datos SQL usan tablas.
  • Las tablas y relvars no son lo mismo, pero pueden serlo para todos los propósitos prácticos.
  • Para usar la teoría de modelado relacional, las tablas deben representar relvars.
  • Para una tabla para representar una variable relacional lo siguiente debe ser cierto:

    1. filas no tienen un orden
    2. columnas no tienen un orden
    3. No hay filas duplicadas
    4. Cada intersección de la columna-fila tiene solo un valor del tipo definido por columna
    5. No hay columnas ocultas especiales (ID de fila, ID de objeto ...)

Por lo tanto, se pueden hacer muchas cosas con mesas y SQL que está fuera del alcance de la teoría de diseño relacional, pero sí perder los beneficios de la "relacional" ...

Técnicamente su puesto (pregunta) tiene dos respuestas.

  • Sí, al título de la publicación.
  • No, al cuerpo de la publicación.
Cuestiones relacionadas