Soft Delete - Используйте Isdeleted Flag или отдельную таблицу столярец?

StackOverflow https://stackoverflow.com/questions/8856684

Вопрос

Должны ли мы использовать флаг для мягких удалений или отдельной столичной стола? Что более эффективно? База данных - SQL Server.

Исходная информация

Некоторое время назад у нас был консультант DB и посмотрел нашу схему базы данных. Когда мы мягким удаляем запись, мы бы обновили бы имещаемый флаг на соответствующей таблице. Было высказано предположение, что вместо использования флага храните удаленные записи в отдельной таблице и используйте соединение, так как это было бы лучше. Я проверил это предложение, но, по крайней мере, на поверхности, дополнительная таблица и соединение выглядит более дорогим, чем использовать флаг.

Первоначальное тестирование

Я настроил этот тест.

Две таблицы, пример и deletedExample. Я добавил некластеризированный индекс на столбце ISDELED.

Я сделал три теста, загрузив миллион записей со следующими удаленными/не удаленными соотношениями:

  • Удален/не снлет
  • 50/50
  • 10/90
  • 1/99

Результаты - 50/5050 50

Результаты - 10/9010 90

Результаты - 1/99enter image description here

Сценарии базы данных, для справки, пример, deletedExample и индекс, например.

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
Это было полезно?

Решение

Числа, которые вы, кажется, указывают на то, что мое первоначальное впечатление был правильным: если ваш самый распространенный запрос по этой базе данных - фильтровать на IsDeleted = 0, Тогда производительность будет лучше с простом битом, особенно если вы используете индексы.

Если вы часто запрашиваетесь на удаленные и неопределенные данные отдельно, то вы можете увидеть прирост производительности, имея таблицу для удаленных элементов, а другой - для неиспользованных предметов, с одинаковыми полями. Но денормализация ваших данных, подобных этим, редко бывает хорошей идеей, так как чаще всего это будет стоить вам гораздо дороже в затратах на обслуживание кода, чем при повышении производительности.

Другие советы

Я не эксперт SQL, но, на мой взгляд, все зависит от частоты использования базы данных. Если к базе данных доступно большое количество пользователей и должна быть эффективной, то использование отдельной таблицы Isledeted будет хорошим. Лучшим вариантом будет использование флага во время производства, и в рамках ежедневной/еженедельной/ежемесячной Maintanace вы можете перемещать все мягкие удаленные записи в таблицу Isdeled и очистить производственную таблицу мягких удаленных записей. Смесь обоих вариантов будет хорошей хорошей.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top