2011-02-12 25 views
5

El diseño orientado a objetos alienta el uso de objetos inmutables para mejorar la seguridad y el rendimiento del hilo. Me pregunto si esto se traslada a las bases de datos relacionales.Base de datos: insertar nuevas filas o actualizar las existentes?

¿Será mejor que actualice las filas existentes o inserte nuevas que actúen como sobrescrituras?

  • caso de uso
    • Cada empleado se asocia con exactamente una empresa
    • empleados cambian de empresa en el tiempo.
    • El nombre del empleado debe ser único.
  • esquema
    • Empleado [nombre, compañía]

Opción 1: Cada vez que un empleado cambia de compañía, insertar un nuevo [nombre, compañía] fila del empleado. La aplicación recibe instrucciones para omitir las filas más antiguas (que se eliminan en una cadena de fondo a lo largo del tiempo). Opción 2: Cada vez que un empleado cambia de compañía, actualice la fila existente.

La opción 1 me recuerda a los objetos inmutables, ya que es seguro para la ejecución de subprocesos (sin necesidad de bloqueos). Por otro lado, cada vez que el empleado cambia de compañía, tengo que clonar todos los objetos asociados y señalarlos en el nuevo registro. Además, no está claro cómo evitar que los Empleados duplicados se creen por error.

La opción 2 facilita la prevención de empleados duplicados, pero tiene la desventaja de devolver asociaciones potencialmente inconsistentes en el aislamiento de transacciones READ_COMMITTED.

Respuesta

4

Estoy publicando esto con la esperanza de que esto ayude a otros en el futuro. Personalmente he perdido innumerables días yendo por este camino (equivocado).

Los objetos inmutables son para tipos de valores (piense en enteros, una marca de tiempo, una lectura de temperatura, etc.). Son tipos que nunca cambiarán.En el momento en que comienzas a hablar de modificar los valores de los Objetos Inmutables, es una indicación bastante fuerte de que estás yendo por el camino equivocado. Cuando usa Objetos Inmutables genuinos, nunca debería tener que actualizar las referencias de los objetos asociados.

Así que la respuesta correcta, ya sea para programación orientada a objetos o diseño de bases de datos, es actualizar los objetos mutables en el lugar.

ACTUALIZACIÓN: marc_s menciona el hecho de que algunos sistemas requieren una pista de auditoría inmutables. Sugiero dividir el sistema en dos. La tabla principal actualiza los datos in situ al insertar copias en una tabla de auditoría separada. Esto tiene dos ventajas:

  1. La tabla principal puede aprovechar las comprobaciones de integridad (es decir, "los nombres de los empleados deben ser exclusivos").
  2. La tabla principal sigue siendo muy rápida para las lecturas y la tabla de auditoría más grande/más lenta se puede recortar con el tiempo.

Esto le permite disfrutar de lo mejor de ambos mundos.

+0

Es fácil recortar un seguimiento de auditoría inmutable, para valores adecuadamente pequeños de "inmutable". Pero en serio, * es * bueno almacenar los datos de auditoría en una tabla diferente. Los datos en la tabla de auditoría no se refieren a la entidad en la tabla original; se trata de la fila. –

1

La diferencia básica es la siguiente:

  • si inserta una nueva fila para cada cambio, y por ejemplo, "Desactivar" la fila anterior configurando una fecha "ValidTo", luego tiene un historial de los cambios en los que, con el tiempo, ingresa al área de una base de datos "temporal"

  • si continúa actualizándose la misma fila una y otra vez, entonces siempre tienes el estado actual, pero no el historial.

así que supongo, esto realmente es la gran pregunta: ¿que hacer necesidad información temporal, por ejemplo, la capacidad de ir "atrás en el tiempo" y ahora ¿cuál era el estado de sus datos hace tres meses? Si es así, la opción 1 (que incluye "eliminaciones suaves", solo marca las filas como eliminadas, en realidad no las elimina) es su única opción. La desventaja es una mayor complejidad y más requisitos de almacenamiento, obviamente.

+1

Ese es un buen punto. Los sistemas auditables requieren un historial inmutable. Dicho esto, ¿no podría separar el sistema en datos en vivo y datos históricos? Live-data se actualizaría en el lugar (simplificando la verificación de integridad) e insertaría una copia en la tabla de auditoría. – Gili

+0

Si utiliza a menudo información temporal y retrocede en el tiempo, es posible que desee considerar una de las nuevas bases de datos de documentos (del mundo NoSQL). Algunos de ellos respaldan explícitamente el fomento de diseños solo de inserción al optimizar su almacenamiento de datos exactamente para ese caso de uso. Eso hace que insertar * mucho * más rápido y mejorar los informes. Los DB relacionales comunes son mejores para cambiar los datos existentes y se vuelven cada vez más lentos con grandes conjuntos de datos (que en su mayoría no es necesario cuando este conjunto de datos solo contiene datos muertos/desactualizados). –

+0

Creo que acabo de repetir tu respuesta marc_s. No plagarismo previsto. – XIVSolutions

0

Esas no son opciones. Son cosas completamente diferentes, y requieren tablas completamente diferentes. La parte dolorosa es que los datos de las tablas pueden parecer exactamente lo mismo. He aquí cómo diferenciarlos.

Cada tabla en una base de datos relacional tiene un único predicado. El predicado determina lo que significan las filas en la tabla. Por lo que una tabla cuyos datos se parece a esto

Name Company 
-- 
Gili Microsoft 
Marc Oracle 

podría significar

Person named "Gili" is currently an employee of company "Microsoft". 
Person named "Marc" is currently an employee of company "Oracle". 

Dicha mesa excluiría a los consultores, porque no son empleados. (En los EE.UU. no lo son, de todos modos.)

pero podría significar

Person named "Gili" once was an employee of company "Microsoft". 
Person named "Marc" once was an employee of company "Oracle". 

y que la mesa también permitirían

Person named "Gili" once was an employee of company "Oracle". 

diferentes predicados, diferentes tablas. (Eso significa que tiene que construir las tablas de manera diferente para captar el significado del predicado.)

Lo que no se puede tener es una tabla que significa

Person named "Gili" is currently an employee of company "Microsoft". 
Person named "Marc" once was an employee of company "Oracle". 

dos predicados diferentes en una misma mesa. No puedo hacerlo en un sistema relacional.

tanto, si su predicado se reduce a esto

Person named NAME is currently an employee of company COMPANY. 

continuación, debe actualizar compañía cuando la persona cambia los empleadores. Y si su predicado se reduce a esto

Person named NAME once was an employee of company COMPANY. 

, entonces debe insertar una nueva fila cuando la persona cambie de empleador.

+1

No estoy de acuerdo.La opción 1 se puede usar para modelar la compañía actual de un empleado si se le ordena al código de la aplicación que solo use el último registro (los registros más antiguos se recortan con el tiempo). Puede que no sea la cosa más intuitiva del mundo, pero técnicamente no tiene nada de malo. – Gili

+0

@Gili: No, no puede. Una tabla creada para implementar las restricciones de casos de uso no le permitirá insertar más de una fila para cada persona. (Eso violaría el predicado.) Ni SQL ni tablas relacionales admiten ningún concepto de "la última fila" en ausencia de una columna para la cual "último" es significativo. El caso de uso claramente no tiene esa columna. Y no se trata de que "el" código de la aplicación reciba instrucciones para hacer algo; se trata de recordar escribir el código * de cada aplicación para hacer exactamente lo mismo, una práctica de desarrollo que se sabe que falla más a menudo de lo que tiene éxito. –

+0

Mi culpa. Quería decir que si tenía Employee [id, name, company] podría insertar varias entradas para el mismo nombre de empleado y que la aplicación solo use la última. "id" se define como una columna de autoincremento que identificaría la "última" fila. Sin embargo, tiene razón sobre una cosa: podría haber múltiples aplicaciones accediendo a la misma base de datos. – Gili

0
tblPerson 
    PersonID 
    LastName 
    FirstName 

tblCompany 
    CompanyID 
    CompanyName 

tblCompany_Employee 
    PersonID 
    CompanyID 
    StartDate 
    EndDate 

Filas nunca se eliminan de tblCompany_Employee - Los registros se insertan cuando una persona es contratada, con una fecha de inicio. En el momento en que finaliza el empleo, EndDate se ACTUALIZA de NULL a la fecha en que terminaron los poderes.

Para buscar empleados actuales para una empresa en particular, SELECCIONE PersonID FROM tblCompanyEmployee WHERE EndDAte IS Null.

para ver el estado del empleo para una persona en particular en una compañía específica:

SELECT PersonID 
FROM tblCompany_Employee 
WHERE PersonID = @PersonID 
AND CompanyID = @CompanyID 
AND EndDate IS Null 

NOTA: Lo anterior probablemente debería ser envuelto en una función que sólo devuelve verdadero de un EmployeeID válido se devuelve - Si la persona Nunca se empleó en la empresa en cuestión la declaración no devolvería registros, por lo tanto falsa.

En este caso, una pista de auditoría se mantiene, y es posible (con un poco de refinamiento additiona, obviamente - He puesto este bonito crudamente aquí) para determinar:

A. La Historia de empleo para una persona en todas las empresas B. todas las personas que han sido empleados por una empresa en particular C que se encuentra actualmente empleado por una determinada empresa D. que no es empleado actualmente por una determinada empresa D. Etc.

Sin perder nunca datos debido a ACTUALIZACIONES que sobrescriben el registro histórico.

1

En general, Data Warehousing tiende a seguir el patrón de "solo insertar". La razón es que todavía se necesitan filas obsoletas en las tablas de domension para ubicar los hechos antiguos en el contexto que existía cuando eran hechos nuevos.

Ejemplo: Pennsylvania fue parte de la región de ventas del noreste hasta el 1 de enero, cuando pasó a formar parte de la región de ventas del Atlántico Medio. Una venta que se realizó en diciembre pasado debe referirse a una fila en la tabla de dimensiones geográficas que lo ubica en la región noreste. Una actualización en lugar de la tabla de dimensiones del "Estado" invalidaría este hecho anterior.

La tendencia en las bases de datos OLTP es realizar actualizaciones en su lugar, y solo hacer un seguimiento de lo que actualmente es el caso. Sin embargo, esto puede provocar la copia de algunos datos en filas de transacciones. Por ejemplo, la fila de detalles de la factura en un sistema de orden de compra puede contener el precio del artículo ordenado, copiado de la fila en la tabla de productos. De esta forma, si el precio se actualiza en la tabla de productos, el precio que afecta a esta factura no se deteriora.

Cuestiones relacionadas