Pregunta

Estoy diseñando un esquema de base de datos, y me pregunto qué criterios debo usar para decidir si cada columna debe ser nullable o no.

¿Debo marcar como NO NULO solo aquellas columnas que absolutamente deben completarse para que una fila tenga algún sentido en mi solicitud?

¿O debo marcar todas las columnas que tengo la intención de que nunca sean nulas?

¿Cuáles son las implicaciones de rendimiento de pequeñas y grandes cantidades de columnas NO NULAS?

Supongo que muchas columnas NOT NULL ralentizarían un poco las inserciones, pero en realidad podría acelerar las selecciones, ya que el generador del plan de ejecución de consultas tiene más información sobre las columnas ...

¿Puede alguien con más conocimiento que yo darme la información?

¿Fue útil?

Solución

Honestamente, siempre pensé que NOT NULL debería ser el valor predeterminado. NULL es el caso especial impar, y debe hacer un caso cada vez que lo use. Además, es mucho más fácil cambiar una columna de NOT NULL a NULABLE que ir a otro lado.

Otros consejos

No hay consecuencias significativas en el rendimiento. Ni siquiera pienses en considerar esto como un problema. Hacerlo es un gran antipatrón de optimización temprana.

" ¿Debería marcar como NOT NULL solo aquellas columnas que se deben completar absolutamente para que una fila tenga algún sentido para mi aplicación? "

Sí Es tan simple como eso. Está mucho mejor con una columna NULLable sin ningún valor NULL en ella, que con la necesidad de NULL y tener que falsificarla. Y de todos modos, cualquier caso ambiguo se filtra mejor en sus Reglas de negocios.


EDITAR:

Hay otro argumento para los campos anulables que creo que es en última instancia el más convincente, que es el argumento del caso de uso. Todos hemos estado sujetos a formularios de entrada de datos que requieren valores para algunos campos; y todos hemos abandonado los formularios donde no teníamos valores sensibles para los campos requeridos. En última instancia, la aplicación, el formulario y el diseño de la base de datos solo son defendibles si reflejan los requisitos del usuario; y está claro que hay muchas, muchas columnas de bases de datos para las cuales los usuarios no pueden presentar ningún valor, a veces en puntos determinados del proceso de negocios, a veces nunca.

Errar en el lado de NOT NULL. En algún momento, tendrá que decidir qué NULL & Quot; significa & Quot; en su aplicación, lo más probable es que haya diferentes cosas para diferentes columnas. Algunos de los casos comunes son & Quot; no especificado & Quot ;, & Quot; desconocido & Quot ;, & Quot; inaplicable & Quot ;, & Quot; hasn ' sucedió todavía " ;, etc. Sabrás cuándo necesitas uno de esos valores, y luego podrás permitir apropiadamente una columna NULLable y codificar la lógica a su alrededor.

Permitir que las cosas al azar sean NULAS es, tarde o temprano, siempre una IME de pesadilla. Use NULL con cuidado y moderación, y sepa lo que significa en su lógica.

Editar: Parece que hay una idea de que estoy discutiendo por NO columnas nulas, alguna vez. Eso es ridículo. NULL es útil, pero solo donde se espera.

El ejemplo DateOfDeath de Le Dorfier es un buen ejemplo. Un NULL DateOfDeath indicaría & Quot; no sucedió todavía & Quot ;. Ahora, puedo escribir una vista LivingPersons WHERE DateOfDeath IS NULL.

Pero, ¿qué significa un NULL OrderDate? ¿Que el pedido aún no se ha realizado? ¿Aunque hay un registro en la tabla de pedidos? ¿Qué tal una dirección NULL? Esos son los pensamientos que deberían pasar por tu cabeza antes de dejar que NULL sea un valor.

Volver a DateOfDeath: una consulta de personas WHERE DateOfDeath > '1/1/1999' no devolvería los registros NULL, aunque lógicamente sabemos que deben morir después de 1999 . ¿Es eso lo que quieres? Si no, entonces será mejor que incluya OR DateOfDeath IS NULL en esa consulta. Si permite que todas las columnas sean NULL, debe pensar en eso cada vez que escribe una consulta . IME, eso es demasiado de un impuesto mental para el 10% de las columnas que realmente tienen un significado legítimo cuando son NULL.

He encontrado que marcar una columna como NOT NULL suele ser una buena idea a menos que tenga un significado útil para NULL en la columna. De lo contrario, puede encontrar NULL inesperadamente allí más tarde cuando se dé cuenta de que no lo quiere, y cambiar es más difícil.

Intento evitar usar NULL en la base de datos tanto como sea posible. Esto significa que los campos de caracteres no siempre son nulos. Lo mismo para los campos numéricos, especialmente cualquier cosa que represente dinero o similar (acciones, unidades, etc.).

Tengo 2 excepciones:

  1. Fechas donde la fecha podría no ser conocida (ej. DivorcedOn)
  2. Relaciones clave fornegn opcionales (MarriedToPersonId). Aunque en ocasiones he usado & Quot; blank & Quot; filas en la tabla de claves foráneas e hicieron obligatoria la relación (por ejemplo, JobDescriptionCode)

También he usado ocasionalmente campos de bits explícitos para " desconocido " / " no establecido " (por ejemplo, JobDescriptionCode e IsEmployeed).

Tengo algunas razones principales por las que:

  1. NULL siempre causará problemas en los campos numéricos. Siempre. Siempre. Siempre. No importa cuán cuidadoso sea en algún momento, seleccione X + Y ya que Total sucederá y devolverá NULL.
  2. NULLs puede causar problemas fácilmente en los campos de cadena, generalmente los campos de dirección (por ejemplo, seleccione AddrLine1 + AddrLine2 de las direcciones).
  3. La protección contra NULL en el nivel de lógica de negocios es un tedioso desperdicio de esfuerzo ... simplemente no los deje en la base de datos y puede guardar cientos de líneas de código.

Mis valores predeterminados preferidos:

  • Cuerdas - > " " ;, también conocido como una cadena vacía
  • Números - > 0
  • Fechas - > Hoy o NULL (ver excepción # 1)
  • Bit - > falso

Puede encontrar la Base de datos en profundidad de Chris Date un recurso útil para este tipo de preguntas. Puede probar sus ideas en esta entrevista , donde dice entre otras cosas:

  

Entonces sí, creo que SQL es bastante malo.   Pero usted pregunta explícitamente cuál es su mayor   los defectos son Bueno, aquí hay algunos:

     
      
  • Duplicar filas
  •   
  • Nulos
  •   
  • Ordenar columnas de izquierda a derecha
  •   
  • Columnas sin nombre y nombres de columna duplicados
  •   
  • Error al admitir " = " correctamente
  •   
  • Punteros
  •   
  • Alta redundancia
  •   

En mi propia experiencia, casi todos " nulos planificados " se puede representar mejor con una tabla secundaria que tiene una clave externa para una tabla base. Participar en la tabla secundaria es opcional, y ahí es donde realmente se hace la distinción nulo / no nulo.

Esto se correlaciona bien con la interpretación de una relación como una proposición lógica de primer orden. También es solo sentido común. Cuando no se conoce la dirección de Bob, se escribe en el Rolodex:

Bob. ____

¿O simplemente se abstiene de completar una tarjeta de dirección para Bob hasta que tenga una dirección real para él?

Editar: El argumento de la fecha aparece en las páginas 53-55 de Base de datos en profundidad, bajo el encabezado de sección " Por qué los nulos están prohibidos ."

Me inclino hacia NOT NULL a menos que vea otra razón, como dijo alguien más, nos guste o no, NULL es el extraño caso especial.

Uno de mis favoritos con respecto a NULL es:

SELECT F1 FROM T WHERE F2 <> 'OK'

... que (al menos en DB2) no incluirá ninguna fila donde f2 sea nulo, porque en la jerga relacional, (NULL < > 'OK') ES NULL. Pero su intención era devolver todas las filas no correctas. Necesita un predicado OR adicional, o escriba F2 DISTINCT FROM 'OK' en su lugar (que es la codificación de casos especiales en primer lugar).

En mi opinión, NULL es solo una de esas herramientas de programación, como la aritmética de punteros o la sobrecarga de operadores, que requiere tanto arte como ciencia.

Joe Celko escribe sobre esto en SQL For Smarties: la trampa de usar NULL en una aplicación es que su significado es, bueno, indefinido. Podría significar desconocido, no inicializado, incompleto, no aplicable, o como en el ejemplo tonto anterior, ¿significa OK o no OK?

Gracias por todas las excelentes respuestas, muchachos. Me diste mucho en qué pensar y me ayudaste a formar mi propia opinión / estrategia, que se reduce a esto:

  

Permitir nulos si-y-solo-si un nulo en   esa columna tendría un específico   significado para su aplicación.

Un par de significados comunes para nulo:

  • Cualquier cosa que venga directamente del usuario
    • Aquí nulo significa " el usuario no ingresó "
    • Para estas columnas, es mejor permitir nulos, o simplemente obtendrá asdasd@asd.com tipo de entrada de todos modos.
  • Claves foráneas para " 0 o 1 " relaciones
    • nulo significa " sin fila relacionada "
    • Entonces permita nulos para estas columnas
    • Este es controvertido , pero esta es mi opinión.

En general, si no puede pensar en un significado útil para nulo en una columna, debería ser NOT NULL. Siempre puede cambiarlo a anulable más tarde.

Ejemplo del tipo de cosas con las que terminé:

create table SalesOrderLine (
    Id int identity primary key,
    -- a line must have exactly one header:
    IdHeader int not null foreign key references SalesOrderHeader, 
    LineNumber int not null, -- a line must have a line number
    IdItem int not null, -- cannot have null item
    Quantity decimal not null, -- maybe could sell 0, but not null
    UnitPrice decimal not null, -- price can be 0, but not null
    -- a null delivery address means not for delivery:
    IdDeliveryAddress int foreign key references Address, 
    Comment varchar(100), -- null means user skipped it
    Cancelled bit not null default (0) -- true boolean, not three-state!
    Delivered datetime, -- null means not yet delivered
    Logged datetime not null default (GetDate()) -- must be filled out
)

Tendería a estar de acuerdo con dorfier.

Sea serio en su aplicación acerca de ser flexible al recibir valores NULL de la base de datos y tratarlos como valores vacíos, y se da mucha flexibilidad para permitir que los NULL se inserten para valores que no especifique.

Probablemente hay muchos casos en los que necesita una integridad de datos muy seria (y / o la intensa optimización de la velocidad de no permitir campos NULL), pero creo que estas preocupaciones se ven atenuadas por el esfuerzo adicional que se necesita para asegurarse de que cada campo tenga un valor predeterminado y / o se establece en un valor razonable.

Apégate con NOT NULL en todo hasta que alguien chille de dolor al respecto. Luego, retírelo en una columna a la vez, de la mejor manera posible. Evite los valores nulos en su base de datos tanto como pueda, durante el tiempo que pueda.

Personalmente, creo que debe marcar las columnas como nulas o no nulas en función del tipo de datos que contienen, si existe un requisito genuino para que los datos siempre estén allí y si los datos siempre se conocen en el momento de entrada. Marcar una columna como no nula cuando los usuarios no tienen los datos obligará a componer los datos, lo que hace que todos sus datos sean inútiles (así es como termina con datos basura como un campo de correo electrónico que contiene & Quot; thisissilly @ Ihatethisaplication.com & Quot;). No requerir algo que debe estar allí para que el proceso funcione (por ejemplo, el campo clave para mostrar qué cliente realizó el pedido) es igualmente estúpido. El vicio nulo no es un problema de integridad de datos en el corazón, haga lo que tenga más sentido para mantener sus datos utilizables.

Si puede pensar a largo plazo, tener NULLs en una columna afecta cómo puede diseñar sus consultas. Si usa declaraciones CASE, COALESCE o tiene que probar explícitamente valores NULL puede tomar la decisión por usted.

Desde el punto de vista del rendimiento, es más rápido no tener que preocuparse por NULLS. Desde el punto de vista del diseño, usar NULL es una manera fácil de saber que un elemento nunca se ha rellenado. Ejemplos útiles incluyen & Quot; UpdatedDateTime & Quot; columnas NULL significa que un elemento nunca se ha actualizado.

Personalmente, permito NULL en la mayoría de las situaciones.

  

¿Cuáles son las implicaciones de rendimiento de pequeñas y grandes cantidades de columnas NO NULAS?

Esto puede indicar lo obvio, pero , cuando una columna es anulable, cada registro requerirá 1 bit adicional de almacenamiento. Por lo tanto, una columna BIT consumirá un 100% más de almacenamiento cuando sea anulable, mientras que un IDENTIFICADOR ÚNICO consumirá solo un 0,8% más de almacenamiento cuando sea anulable.

En el caso patológico, si su base de datos tiene una sola tabla que consta de una sola columna BIT, la decisión de anular esa columna reduciría el rendimiento de su base de datos a la mitad. Sin embargo, en la gran mayoría de los escenarios del mundo real, la nulabilidad no tendrá un impacto medible en el rendimiento.

El uso de 'No nulo' o 'Nulo' debe basarse principalmente en sus requisitos de persistencia particulares.

Tener un valor Nullable significa que hay dos o tres estados (tres estados con campos de Bit)

Por ejemplo; si tuviera un campo de bits que se llamaba 'IsApproved' y el valor se establece en una etapa posterior a la inserción. Luego hay tres estados:

  1. 'IsApproved' Sin respuesta
  2. 'IsApproved' está aprobado
  3. 'IsApproved' no está aprobado

Por lo tanto, si un campo puede considerarse legítimamente Sin respuesta y no hay un valor predeterminado que sea adecuado. Se debe considerar que estos campos son anulables

Cualquier columna anulable es una violación de la tercera forma normal.

Pero, esa no es una respuesta.

Tal vez esto es: hay dos tipos de columnas en las bases de datos: las que contienen la estructura de los datos y las que contienen el contenido de los datos. Las claves son estructura, los campos ingresables por el usuario son datos. Otras cosas, bueno, es una decisión judicial.

Las cosas que son estructura, que se usan en cláusulas de unión, generalmente no son nulas. Las cosas que son datos suelen ser anulables.

Cuando tiene una columna que contiene una de una lista de opciones o es nula (no se elige), generalmente es una buena idea tener un valor específico para " no se elige " en lugar de una columna anulable. Este tipo de columnas a menudo participan en uniones.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top