Recuerdo haber leído este artículo sobre diseño de bases de datos y también recuerdo que decía que debería tener propiedades de campo de NOT NULL. Sin embargo, no recuerdo por qué este fue el caso.
Todo lo que puedo pensar es que, como desarrollador de aplicaciones, no tendrías que probar NULL y un posible valor de datos inexistente (por ejemplo, una cadena vacía para cadenas).
Pero, ¿qué hace en el caso de fechas, fecha y hora (SQL Server 2008)? Tendría que usar una fecha histórica o de fondo.
¿Alguna idea sobre esto?
database-design
null
Thomas Stringer
fuente
fuente
Respuestas:
Creo que la pregunta está mal formulada, ya que la redacción implica que ya has decidido que los NULL son malos. Quizás quisiste decir "¿Deberíamos permitir NULL?"
De todos modos, aquí está mi opinión: creo que los NULL son algo bueno. Cuando comienzas a prevenir NULLs solo porque "NULLs son malos" o "NULLs son difíciles", comienzas a inventar datos. Por ejemplo, ¿qué pasa si no sabes mi fecha de nacimiento? ¿Qué vas a poner en la columna hasta que lo sepas? Si eres como mucha gente anti-NULL, vas a ingresar 1900-01-01. Ahora me colocarán en la sala geriátrica y probablemente recibiré una llamada de mi estación de noticias local felicitándome por mi larga vida, preguntándome mis secretos para vivir una vida tan larga, etc.
Si se puede ingresar una fila donde es posible que no se conozca el valor de una columna, creo que NULL tiene mucho más sentido que elegir un valor de token arbitrario para representar el hecho de que es desconocido, un valor que otros tendrán ya tiene que saber, realizar ingeniería inversa o preguntar para averiguar qué significa.
Sin embargo, hay un equilibrio: no todas las columnas de su modelo de datos deben ser anulables. A menudo hay campos opcionales en un formulario, o piezas de información que de otro modo no se recopilarían en el momento en que se crea la fila. Pero eso no significa que pueda diferir el llenado de todos los datos. :-)
Además, la capacidad de usar NULL puede verse limitada por requisitos cruciales en la vida real. En el campo médico, por ejemplo, puede ser un asunto de vida o muerte saber por qué se desconoce un valor. ¿La frecuencia cardíaca es NULA porque no había pulso o porque aún no la hemos medido? En tal caso, ¿podemos poner NULL en la columna de frecuencia cardíaca y tener notas o una columna diferente con un motivo NULL porque?
No tenga miedo de los NULL, pero esté dispuesto a aprender o dictar cuándo y dónde deben usarse, y cuándo y dónde no deben usarse.
fuente
birth_date
donde almacena las fechas de nacimiento? Si se desconoce la fecha de nacimiento, simplemente no inserte la fecha de nacimientobirth_date
. Los nulos son un desastre.1900-01-01
para evitar tener un valor de fecha / hora NULL? OK entonces. Además, NULL = desconocido y desconocido = falso. No estoy seguro de qué problemas podría causar esto, aparte de que las personas no nacen sabiendo eso (como si no nacieran sabiendo muchas cosas inherentes a un RDBMS complejo). Nuevamente, agitando las manos y diciendo "¡Problema! ¡Desastre!" No lo hace así.Las razones establecidas son:
NULL no es un valor y, por lo tanto, no tiene ningún tipo de datos intrínsecos. Los nulos necesitan un manejo especial en todo el lugar cuando el código que de otra manera se basa en tipos reales también podría recibir el NULL sin escribir.
NULL rompe la lógica de dos valores (familiar verdadero o falso) y requiere una lógica de tres valores. Esto es mucho más complejo de implementar incluso correctamente, y ciertamente la mayoría de los DBA y casi todos los que no son DBA lo entienden mal. Como consecuencia, invita positivamente a muchos errores sutiles en la aplicación.
El significado semántico de cualquier NULL específico se deja a la aplicación , a diferencia de los valores reales.
Semánticas como "no aplicable" y "desconocido" y "centinela" son comunes, y también hay otras. Con frecuencia se usan simultáneamente dentro de la misma base de datos, incluso dentro de la misma relación; y, por supuesto, son significados no explícitos, indistinguibles e incompatibles .
No son necesarios para las bases de datos relacionales , como se argumenta en "Cómo manejar la información que falta sin nulos" . Una mayor normalización es un primer paso obvio para intentar deshacerse de una tabla de NULL.
Esto no significa que NULL nunca deba permitirse. Se tiene que recordar que hay muchas buenas razones para no permitir NULL siempre que sea posible.
Significativamente, aboga por esforzarse mucho, a través de un mejor diseño de esquema y mejores motores de base de datos, e incluso mejores lenguajes de bases de datos, para hacer posible evitar NULL con más frecuencia.
Fabian Pascal responde a una serie de argumentos, en "Nulls Nullified" .
fuente
No estoy de acuerdo, los nulos son un elemento esencial del diseño de la base de datos. La alternativa, como también aludiste, sería una proliferación de valores conocidos para representar lo que falta o lo desconocido. El problema radica en que nulo es tan ampliamente incomprendido y, como resultado, se usa de manera inapropiada.
IIRC, Codd sugirió que la implementación actual de nulo (es decir, no presente / faltante) podría mejorarse con dos marcadores nulos en lugar de uno, "no presente pero aplicable" y "no presente y no aplicable". No puedo imaginar cómo los diseños relacionales mejorarían personalmente.
fuente
null
, y una lógica multivalor definida por el usuario para acompañarlos: pPermítanme comenzar diciendo que no soy un DBA, soy un desarrollador de memoria y mantengo y actualizo nuestras bases de datos en función de nuestras necesidades. Dicho esto, tuve la misma pregunta por varias razones.
Paso mucho tiempo analizando las numerosas respuestas, comentarios, artículos y consejos en Internet. No hace falta decir que la mayor parte de la información era casi la misma que la respuesta de @ AaronBertrand. Por eso sentí la necesidad de responder a esta pregunta.
En primer lugar, quiero aclarar algo para todos los futuros lectores ... Los valores NULL representan datos desconocidos, NO datos no utilizados. Si tiene una tabla de empleados que tiene un campo de fecha de finalización. Un valor nulo en la fecha de finalización se debe a que es un campo requerido en el futuro que actualmente se desconoce. Cada empleado, ya sea activo o despedido, en algún momento tendrá una fecha agregada a ese campo. Esa es, en mi opinión, la única razón para un campo Nullable.
Dicho esto, la misma tabla de empleados probablemente contenga algún tipo de datos de autenticación. Es común en un entorno empresarial que los empleados aparezcan en la base de datos de recursos humanos y contabilidad, pero no siempre tienen o necesitan detalles de autenticación. La mayoría de las respuestas lo llevarán a creer que está bien anular esos campos o, en algunos casos, crear una cuenta para ellos, pero nunca enviarles las credenciales. ¡El primero hará que su equipo de desarrollo escriba código para verificar NULL y tratarlos en consecuencia y el segundo representa un gran riesgo de seguridad! Las cuentas que aún no se usan en el sistema solo aumentan la cantidad de puntos de acceso posibles para un hacker, además de que ocupan un valioso espacio en la base de datos para algo que nunca se usa.
Dada la información anterior, la mejor manera de lidiar con los datos anulables que se utilizarán es permitir valores anulables. Es triste pero cierto y tus desarrolladores te odiarán por ello. El segundo tipo de datos anulables debe colocarse en una tabla relacionada (IE: cuenta, credenciales, etc.) y tener una relación uno a uno. Esto permite que un usuario exista sin credenciales a menos que sean necesarias. Esto elimina el riesgo adicional de seguridad, el valioso espacio de la base de datos y proporciona una base de datos mucho más limpia.
A continuación se muestra una estructura de tabla muy simplista que muestra tanto la columna anulable requerida como una relación uno a uno.
Sé que llego un poco tarde a la fiesta ya que esta pregunta se hizo hace años, pero espero que esto ayude a arrojar algo de luz sobre este tema y la mejor manera de tratarlo.
fuente
TerminationDate
en los registros de los empleados, pero tenga una tabla para laTerminatedEmployee
cual los empleados sean trasladados (no copiados) por la aplicación cuando sean despedidos. Obviamente, esto funciona bien con la tabla Cuenta porque no habrá una cuenta vinculada en laTerminatedEmployee
tabla. Si todavía necesita los números de teléfono, invertiría las claves foráneas para que las tablas de empleados y empleados despedidos tengan la identificación del número de teléfono en lugar de lo contrario.Además de todos los problemas con los desarrolladores confusos de NULL, los NULL tienen otro inconveniente muy serio: el rendimiento
Las columnas NULL'able son un desastre desde una perspectiva de rendimiento. Considere la aritmética de enteros como un ejemplo. En un mundo sano sin NULL, es "fácil" vectorizar la aritmética de enteros en el código del motor de la base de datos utilizando las instrucciones SIMD para realizar prácticamente cualquier cálculo a velocidades superiores a 1 fila por ciclo de CPU. Sin embargo, en el momento en que introduce NULL, debe manejar todos los casos especiales que crea NULL. Los conjuntos de instrucciones de CPU modernos (léase: x86 / x64 / ARM y lógica de GPU también) simplemente no están equipados para hacer esto de manera eficiente.
Considere la división como un ejemplo. En un nivel muy alto, esta es la lógica que necesita con un entero no nulo:
Con NULL, esto se vuelve un poco más complicado. Junto con
b
usted necesitará un indicador sib
es nulo y de manera similar paraa
. El cheque ahora se convierte en:La aritmética NULL es significativamente más lenta para ejecutarse en una CPU moderna que la aritmética no nula (por un factor de alrededor de 2-3x).
Empeora cuando presentas SIMD. Con SIMD, una CPU Intel moderna puede realizar 4 divisiones enteras de 32 bits en una sola instrucción, como esta:
Ahora, también hay formas de manejar NULL en SIMD land, pero esto requiere el uso de más vectores y registros de CPU y hacer un poco de enmascaramiento de bits inteligente. Incluso con buenos trucos, la penalización de rendimiento de la aritmética de enteros NULL se desliza en el rango más lento 5-10x incluso para expresiones relativamente simples.
Algo como lo anterior vale para los agregados y, en cierta medida, también para las uniones.
En otras palabras: la existencia de NULL en SQL es un desajuste de impedancia entre la teoría de la base de datos y el diseño real de las computadoras modernas. Hay una razón bastante buena por la que NULL confunde a los desarrolladores, porque un número entero no puede ser NULL en la mayoría de los lenguajes de programación sanos, así no es cómo funcionan las computadoras.
fuente
Preguntas interesantes
Es más complicado que eso. Nulo tiene varios significados distintos y una razón realmente importante para no permitir nulos en muchas columnas es que cuando la columna es nula, esto significa una y solo una cosa (es decir, que no apareció en una unión externa). Además, le permite establecer estándares mínimos de entrada de datos, lo cual es realmente útil.
Eso ilustra un problema con los valores nulos de inmediato, a saber, que un valor almacenado en una tabla puede significar "este valor no se aplica" o "no lo sabemos". Con las cadenas, una cadena vacía puede servir como "esto no se aplica" pero con fechas y horas, no existe tal convención porque no hay un valor válido que convencionalmente signifique esto. Por lo general, estará atascado con NULL.
Hay formas de evitar esto (agregando más relaciones y uniéndose), pero plantean exactamente los mismos problemas de claridad semántica que tener NULL en la base de datos. Para estas bases de datos no me preocuparía por esto. Simplemente no hay nada que puedas hacer al respecto realmente.
EDITAR: Un área donde los NULL son indispensables es en las claves externas. Aquí generalmente tienen un solo significado, idéntico al nulo en el significado de unión externa. Esta es una excepción al problema, por supuesto.
fuente
El artículo de Wikipedia sobre SQL Null tiene algunas observaciones interesantes sobre el valor NULL, y como respuesta independiente de la base de datos, siempre y cuando conozca los posibles efectos de tener valores NULL para su RDBMS específico, son aceptables en su diseño. Si no lo fueran, no podría especificar columnas como anulables.
Solo tenga en cuenta cómo su RDBMS los maneja en operaciones SELECT, como las matemáticas, y también en los Índices.
fuente
Wow, la respuesta correcta "No permitir NULLs cuando no es necesario porque degradan el rendimiento" es de alguna manera la última respuesta calificada. Lo votaré y elaboraré. Cuando un RDBMS permite NULL para una columna no dispersa, esa columna se agrega a un mapa de bits que rastrea si el valor es NULL para cada fila individual. Por lo tanto, al agregar la capacidad NULL a una columna en una tabla donde todas las columnas no permiten NULL, está aumentando el espacio de almacenamiento requerido para guardar la tabla. Además, necesita que el RDBMS lea y escriba en el mapa de bits, lo que degrada el rendimiento en todas las operaciones.
Además, en varios casos, permitir NULLs romperá 3NF. Si bien no soy un fanático de 3NF como muchos de mis colegas, considere el siguiente escenario:
En la tabla Persona hay una columna, llamada DateOfDeath, que es anulable. Si una persona ha fallecido, se completará con su DateOfDeath; de lo contrario, se dejará como NULL. También hay una columna de bits no anulable llamada IsAlive. Esta columna se establece en 1 si la persona está viva y 0 si la persona está muerta. La gran mayoría de los procedimientos almacenados usan la columna IsAlive, solo les importa si una persona está viva, no su DateOfDeath.
Sin embargo, la columna IsAlive rompe la normalización de la base de datos, porque es completamente derivable de DateOfDeath. Pero dado que IsAlive está conectado a la mayoría de los SP, la solución directa es hacer que DateOfDeath no sea anulable y asignar un valor predeterminado a la columna en caso de que la persona aún esté viva. Los pocos SP que usan DateOfDeath pueden reescribirse para verificar la columna IsAlive, y solo honran a DateOfDeath si la persona no está viva. Nuevamente, dado que la mayoría de los SP solo se preocupan por IsAlive (un poco) y no por DateOfDeath (una fecha), el uso de este patrón acelera considerablemente el acceso.
Una secuencia de comandos T-SQL útil para encontrar columnas anulables sin NULL en todos los esquemas es:
Si ejecuta esto en una copia de su base de datos de producción, puede encontrar las columnas marcadas por los desarrolladores que permiten NULL que no tienen NULL en la práctica. La gran mayoría de estos pueden marcarse como NO NULOS, lo que aumenta el rendimiento y reduce el espacio de almacenamiento.
Puede que no sea posible eliminar todos los NULL en todas las tablas y aún así tener un diseño limpio, pero existe una ventaja considerable en eliminar tantos NULL como sea posible. El optimizador funciona mucho más rápido con esta información, y si puede eliminar todos los NULL en una tabla, puede recuperar una cantidad considerable de espacio de almacenamiento.
Sé que el rendimiento no es algo en lo que los DBA piensen demasiado, pero solo puede arrojar una cantidad limitada de memoria y potencia de procesador en una solución, en algún momento tendrá que comenzar a pensar en un diseño lógico y físico. .
También tenga en cuenta que esto es solo para verdaderos RDBMS y estoy basando la parte técnica de mis respuestas en SQL Server. El T-SQL listado para encontrar columnas anulables sin nulos también es de SQL Server.
fuente