2012-01-13 5 views
8

¿Deberíamos usar un indicador para eliminaciones suaves, o una tabla de unión separada? ¿Cuál es más eficiente? La base de datos es SQL Server.Eliminación suave: use la marca IsDeleted o la tabla de unión separada.

Antecedentes

Hace un tiempo tuvimos un consultor DB entrar y mirar a nuestro esquema de base de datos. Cuando eliminemos un registro de forma suave, actualizaríamos un indicador IsDeleted en la (s) tabla (s) correspondiente (s). Se sugirió que, en lugar de utilizar una bandera, almacenara los registros eliminados en una tabla separada y utilizara una combinación, ya que eso sería mejor. He puesto esa sugerencia a prueba, pero al menos en la superficie, la mesa extra y la combinación parecen ser más caras que usar una bandera.

Prueba Inicial

He creado esta prueba.

Dos tablas, ejemplo y ejemplo eliminado. Agregué un índice no agrupado en la columna IsDeleted.

lo hice tres pruebas, la carga de un millón de registros con las siguientes relaciones borrados/no eliminados:

  • eliminados/NonDeleted
  • 50/50
  • 10/90
  • 1/99

resultados - 50/50 50 50

Resultados - 10/90 10 90

Resultados - 1/99 enter image description here

scripts de base, para la referencia, Ejemplo, DeletedExample, y el Índice de Example.IsDeleted

CREATE TABLE [dbo].[Example](
    [ID] [int] NOT NULL, 
    [Column1] [nvarchar](50) NULL, 
    [IsDeleted] [bit] NOT NULL, 
CONSTRAINT [PK_Example] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 

ALTER TABLE [dbo].[Example] ADD CONSTRAINT [DF_Example_IsDeleted] DEFAULT ((0)) FOR [IsDeleted] 
GO 

CREATE TABLE [dbo].[DeletedExample](
    [ID] [int] NOT NULL, 
CONSTRAINT [PK_DeletedExample] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 

ALTER TABLE [dbo].[DeletedExample] WITH CHECK ADD CONSTRAINT [FK_DeletedExample_Example] FOREIGN KEY([ID]) 
REFERENCES [dbo].[Example] ([ID]) 
GO 

ALTER TABLE [dbo].[DeletedExample] CHECK CONSTRAINT [FK_DeletedExample_Example] 
GO 

CREATE NONCLUSTERED INDEX [IX_IsDeleted] ON [dbo].[Example] 
(
    [IsDeleted] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO 

Respuesta

8

Los números que parece indicar que my initial impression eran correctos: si su consulta más común contra esta base de datos es filtrar en IsDeleted = 0, entonces el rendimiento será mejor con un simple indicador de bit, especialmente si hace un uso racional de los índices.

Si consulta a menudo los datos eliminados y recuperados por separado, entonces puede ver una ganancia en el rendimiento al tener una tabla para elementos eliminados y otra para elementos no recuperados, con campos idénticos. Pero la desnormalización de sus datos de este tipo rara vez es una buena idea, ya que a menudo le costará mucho más en costos de mantenimiento de código que lo que le permitirá aumentar el rendimiento.

+2

Buena respuesta. También considere usar índices filtrados.Si solo consulta la tabla Ejemplo por Columna1 cuando los registros no se eliminan, indexe Columna1 "DONDE IsDelete = 0". –

1

I No soy el experto SQL, pero en mi opinión, todo depende de la frecuencia de uso de la base de datos. Si la gran cantidad de usuarios accede a la base de datos y necesita ser eficiente, el uso de una tabla independiente de Eliminación será buena. La mejor opción sería utilizar un indicador durante el tiempo de producción y, como parte del mantenimiento diario/semanal/mensual, puede mover todos los registros borrados a la tabla isDeleted y borrar la tabla de producción de los registros eliminados. La mezcla de ambas opciones será buena.

Cuestiones relacionadas