Pregunta

¿Deberíamos usar una bandera para eliminaciones suaves o una tabla de carpintería separada? ¿Cuál es más eficiente? La base de datos es SQL Server.

Información de contexto

Hace un tiempo tuvimos un consultor de DB y miramos nuestro esquema de base de datos. Cuando suavizamos un registro, actualizaríamos un indicador ISDELELED en las tablas apropiadas. Se sugirió que en lugar de usar una bandera, almacene los registros eliminados en una mesa separada y use una unión, ya que sería mejor. He puesto esa sugerencia a la prueba, pero al menos en la superficie, la tabla adicional y la unión parecen ser más caras que usar una bandera.

Prueba inicial

He configurado esta prueba.

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

Hice tres pruebas, cargando un millón de registros con las siguientes relaciones eliminadas/no eliminadas:

  • Eliminado/no sedimentado
  • 50/50
  • 10/90
  • 1/99

Resultados - 50/5050 50

Resultados - 10/9010 90

Resultados - 1/99enter image description here

Scripts de base de datos, como referencia, ejemplo, DeletedExample e índice, por ejemplo.

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
¿Fue útil?

Solución

Los números que tienes que indicar que Mi impresión inicial fue correcto: si su consulta más común contra esta base de datos es filtrar IsDeleted = 0, entonces el rendimiento será mejor con un indicador de bits simple, especialmente si hace un uso acantilado de los índices.

Si a menudo consulta los datos eliminados y no descartados por separado, entonces podría ver una ganancia de rendimiento teniendo una tabla para elementos eliminados y otra para elementos no enredados, con campos idénticos. Pero denormalizar sus datos de esta manera rara vez es una buena idea, ya que a menudo le costará mucho más en los costos de mantenimiento del código de lo que le obtendrá los aumentos de rendimiento.

Otros consejos

No soy el experto en 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 debe ser eficiente, entonces el uso de una tabla de ISDELELED separada será bueno. La mejor opción sería usar una bandera durante el tiempo de producción y, como parte del mantenace diario/semanal/mensual, puede mover todos los registros eliminados suaves a la tabla ISDeleted y borrar la tabla de producción de los registros eliminados suaves. La mezcla de ambas opciones será buena.

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