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:
select 'IF NOT EXISTS (SELECT 1 FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ' WHERE ' + QUOTENAME(c.name) + ' IS NULL)
AND (SELECT COUNT(*) FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ') > 1 PRINT ''' + s.name + '.' + t.name + '.' + REPLACE(c.name, '''', '''''') + ''''
from sys.columns c
inner join sys.tables t ON c.object_id = t.object_id
inner join sys.schemas s ON s.schema_id = t.schema_id
where c.is_nullable = 1 AND c.is_computed = 0
order by s.name, t.name, c.name;
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.