Tinyint vs Bit?

81

No quiero iniciar una guerra religiosa aquí, pero parece haber dos escuelas de pensamiento sobre cómo representar valores booleanos en una base de datos. Algunos dicen que bites el tipo de datos apropiado, mientras que otros sostienen que tinyintes mejor.

Las únicas diferencias que conozco son estas:

  • bit: el tamaño de almacenamiento es de 1 bit, los valores posibles son 0 o 1
  • tinyint: el tamaño de almacenamiento es de 1 byte, los valores posibles son 0-255

¿Qué tipo de datos es mejor cuando necesita representar valores booleanos? ¿ tinyintVale la pena la sobrecarga adicional "por si acaso" necesita valores> 1?

Seibar
fuente
1
"Por si acaso" parece un diseño de base de datos bastante fluido. ¿Por qué no almacenar todo como NVARCHAR (MAX) y cubrir todas sus bases?
Stuart Ainsworth
TinyInt es mi preferencia. Luego, al hacer recuentos agregados contra el campo, no tiene que lanzarlo. Además, algunos lenguajes de front-end interpretan un Bit de manera diferente a otros, y el uso de TinyInt hace que las comprobaciones de validación sean universales para cualquier lenguaje de front-end.
Gregory Hart
Acabo de encontrar una rareza con bit en phpMyAdmin. Cuando le digo que deje que el campo sea NULL y no se establezca ningún valor predeterminado, el valor predeterminado es <em> NULL </em> en lugar de NULL. +1 para tinyint por cierto
Vörös Amadea
al importar el archivo csv del formulario 1 funciona en el caso de tinyint (1), pero en el caso del bit (1) debe reemplazarlo por b'1 '
Rajat

Respuestas:

90

Cuando agrega una columna de bits a su tabla, ocupará un byte completo en cada registro, no solo un bit. Cuando agrega una segunda columna de bits, se almacenará en el mismo byte. La columna del noveno bit requerirá un segundo byte de almacenamiento. Las tablas con una columna de 1 bit no obtendrán ningún beneficio de almacenamiento.

Tinyint y bit se pueden hacer que funcionen, he usado ambos con éxito y no tengo muchas preferencias.

ScottS
fuente
Ese es un comentario muy útil y su reputación es bastante buena, pero ¿tiene alguna referencia que lo respalde? ¿Es un detalle de implementación o todos los motores lo manejan de la misma manera?
Jon z
3
@Jonz Vea aquí para MySQL.
shmosel
19

Bit ... a menos que pertenezcas al clan "verdadero / falso / archivo no encontrado"

En caso de que no haya obtenido la referencia ...

Y en el caso de Linq2SQL, bit funciona con verdadero / falso, lo que facilita la programación. Ambos tienen ventajas.

Y también hay que tener en cuenta el mantenimiento de la programación. ¿Qué sucede si usted (o un programador en prácticas junior) utiliza un 2, 3, 25, 41, 167, 200, etc.? ¿Dónde está eso documentado? Los bits se autodocumentan y son bastante universales.

Mike Robinson
fuente
11
los bits son anulables, por lo que aún puede tener T / F / FNF.
Austin Salonen
3
¿Y qué tan malvado es NULL igual a FNF? :) Realmente digno de thedailywtf!
John Rudy
@Pratik el problema es NULO significa que no hay valor en la base de datos. No significa archivo no encontrado. Haga esto y comenzará a codificar implícitamente estados en sus filas que son difíciles de documentar y confusos. Es como tener una mesa de artículos. ¿Cómo puedo ver si se ha vendido un artículo? Podría ver si tiene un precio de venta, una fecha de venta, un nombre de compradores, etc. O podría hacer cumplir todo eso con una restricción de verificación y crear un campo de bits para los artículos vendidos.
CodeMonkey
15

Utilizo bits cuando es apropiado. Además de ser semánticamente del tipo correcto (¡la semántica cuenta!), Varios campos de bits (hasta 8) en una sola fila (en SQL Server, de todos modos) se pueden consolidar en un solo byte de almacenamiento. Después del octavo, se necesita un byte adicional para los siguientes 8, y así sucesivamente.

Referencias:

John Rudy
fuente
5

Para usuarios de MySql: por qué no debería usar columnas BIT en MySQL

armandino
fuente
12
Hmmm, se parece más a una entrada "Por qué no debería usar MySQL" ... :-)
Brian Knoblauch
1
corregido: anotado en 5.0.23, 5.1.12 registros de cambios. Las columnas BIT de una tabla pueden hacer que las combinaciones que usan la tabla fallen.
Antti Rytsölä
2

Booleano, por definición, permite solo dos valores. ¿Por qué necesitarías algo más que un bit para esto? si necesita una lógica de tres (o más) estados, utilice un tipo de datos más grande, pero me quedaría (y lo haré) con los campos de bits para la lógica booleana estándar.

tvanfosson
fuente
2

Utilizo bit porque me ahorra tener que usar una restricción de verificación y porque mi ORM convertirá automáticamente bit en un booleano anulable (C #), que aprecio mucho una vez que codifico.

RedFilter
fuente
2

Espacio cero para falso

Cualquiera que sea su elección, puede configurarlo en NULLlugar de 0y no ocupará espacio adicional (ya que la base de datos casi siempre tiene una NULLbandera para cada campo de cada fila, simplemente allí; más información aquí ). Si también se asegura de que el valor predeterminado / más probable sea false, ¡ahorrará aún más espacio!

Algo de espacio para la verdad

El valor a representar truerequiere el espacio definido por el tipo de campo; el uso BITsolo ahorrará espacio si una tabla tiene varias columnas de este tipo, ya que usa un byte por cada 8 campos (frente a lo TINYINTque usa un byte por campo).

TINYINTtiene la ventaja de permitirle personalizar una máscara de bits de 8 valores sin preocuparse por administrar un montón de columnas adicionales, y la búsqueda es teóricamente más rápida (un campo de un solo número entero frente a varios campos de bits). Pero hay algunas desventajas, como un orden más lento, elementos elegantes de indexación cruzada y la falta de nombres de campo. Lo cual para mí es la mayor pérdida; su base de datos requeriría documentación externa para anotar qué bits hicieron qué en qué máscaras de bits.

En cualquier caso, evite la tentación de utilizar TEXTcampos para almacenar valores booleanos o conjuntos de ellos. La búsqueda en el texto es mucho más trabajo para el servidor y los esquemas de nombres arbitrarios como "encendido, apagado, apagado" pueden dañar la interoperabilidad.

Beejor
fuente
1

Intenté agrupar en bit (SQL Server 2k5) y funcionó bien para mí. Me gusta usar el tipo de datos correcto para la aplicación. Si es un campo verdadero / falso, entonces lo que uso es bit ...

Robar
fuente
1

Todas estas discusiones teóricas son geniales, pero en realidad, al menos si está usando MySQL y realmente para SQLServer también, es mejor quedarse con datos no binarios para sus booleanos por la sencilla razón de que es más fácil trabajar con ellos cuando están generando datos, consultando, etc. Es especialmente importante si está intentando lograr interoperabilidad entre MySQL y SQLServer (es decir, sincroniza datos entre los dos), porque el manejo del tipo de datos BIT es diferente en los dos. Entonces, en la práctica, tendrá muchas menos molestias si se queda con un tipo de datos numérico. Recomendaría que MySQL se quede con BOOL o BOOLEAN, que se almacena como TINYINT (1). Incluso la forma en que MySQL Workbench y MySQL Administrator muestran el tipo de datos BIT no es agradable (es un pequeño símbolo para datos binarios).

Sheldmandu
fuente
1

No creo que lo vi mencionado anteriormente, pero existe el problema de no poder agregar columnas BIT (por ejemplo, MIN, MAX y especialmente SUM). Acabo de probar con 2008 y el problema sigue ahí. Esa es la razón más importante por la que uso tinyint últimamente, la otra es que me gusta la escala de tinyint, siempre es un fastidio cuando la bandera de bits de "dos valores" de repente necesita más valores posibles.

saldag
fuente
1
Puede agregarlos lanzándolos a otro tipo de datos. ¿Por qué necesitaría sumar verdadero / falso?
Martin Smith
2
Con frecuencia agrupamos en un campo y sumamos cuántos de otro campo es verdadero para cada grupo por resultado, la alternativa a la suma sería devolver el resultado completo al código y repetirlo allí, lo que a veces resulta en devolver 1000 veces más datos al cliente . Pero el casting elimina eso, así que no es un problema.
David Mårtensson
0

Construimos todas nuestras tablas con un campo "vector" int. Luego usamos ese campo como una colección de 32 bits que podemos asignar para cualquier propósito. (Potencialmente usando un grupo de bits para un conjunto de estados). Evita que tengamos que seguir agregando campos de bandera si lo olvidamos.

Joe
fuente
2
También se llama ofuscación. O, para el profano, "pesadilla de mantenimiento".
Robert C. Barth
6
Puede convertir todas sus tablas en una sola columna de TEXTO y poner todo allí delimitado por comas. Entonces nunca tendría que cambiar su modelo de datos.
Tom H
1
Tenemos un entorno un tanto único. Tenemos conjuntos de datos extremadamente grandes Y tiempo de actividad de 49, por lo que alterar las tablas es bastante prohibitivo (el doble que cuando se trata de replicación). Realizamos un seguimiento de todos los bits en una ubicación centralizada, lo que ayuda a evitar el problema de mantenimiento.
Joe
0

@Kevin: Creo que puedes usar group byen campos de bits (SQL Server 2005):

declare @t table (
    descr varchar(10),
    myBit1 bit, 
    myBit2 bit
)
insert into @t values ('test1', 0, 1)
insert into @t values ('test2', 1, 0)
insert into @t values ('test3', 1, 1)
insert into @t values ('test4', 0, 0)

select myBit1, count(myBit1) from @t group by myBit1
select myBit2, count(myBit1) from @t group by myBit2

Resultados:

myBit1 
------ -----------
0      2
1      2

myBit2 
------ -----------
0      2
1      2
Seibar
fuente
0

TinyInt es mi preferencia. Entonces, al hacer recuentos agregados contra el campo, no tiene que lanzarlo. Además, algunos lenguajes front-end interpretan un Bit de manera diferente a otros, y el uso de TinyInt hace que las comprobaciones de validación sean universales para cualquier lenguaje front-end.

Gregory Hart
fuente
-2

Me gusta usar char (1) con 'T' o 'F'. Sí, se puede abusar de otros valores, pero al menos es fácil de ver en informes u otros lugares donde es más difícil trabajar con valores de bits o binarios.

Darryl Braaten
fuente
2
Puede (y debe) agregar fácilmente una restricción a la columna para permitir solo "T" y "F". Dicho esto, la capa de informes debe estar COMPLETAMENTE SEPARADA de la base de datos. No debe alterar el esquema de su base de datos solo con el propósito de cómo se mostrará una columna.
Tom H
Estoy de acuerdo con Darryl. Dada la falta de soporte para los tipos booleanos en los sistemas RDBMS generales (MySQL no está solo aquí) T / F (en realidad prefiero Y / N) es mucho más legible. Si bien estoy de acuerdo en principio con los comentarios de Tom H, creo que la legibilidad es mucho más importante de lo que él cree. ¡Los desarrolladores de bases de datos no miran la interfaz cuando cambian el código de otra persona! Además, no siempre está necesariamente claro en qué sentido un desarrollador considera que son 1 y 0. Si todos lo estuviéramos haciendo de la manera "adecuada" a la antigua, estaríamos usando -1para representar verdadero y 0para representar falso.
cartbeforehorse
A mi comentario anterior, debo agregar que parece que MySQL no admite restricciones CHECK, lo que complicaría la opción T / F, ya que no puede evitar que la columna esté poblada por cualquier otro carácter del alfabeto. No está bien.
cartbeforehorse