2012-01-13 10 views
8

Czy powinniśmy używać flagi do miękkich operacji usuwania lub oddzielnego stołu stolarskiego? Który jest bardziej wydajny? Baza danych to SQL Server.Soft Delete - Użyj flagi IsDeleted lub oddzielnego stołu stolarskiego?

Informacja Tło

Jakiś czas temu mieliśmy konsultant DB przyjść i spojrzeć na nasze schematu bazy danych. Po miękkim usunięciu rekordu zaktualizujemy flagę IsDeleted na odpowiednich tabelach. Zasugerowano, że zamiast używać flagi, przechowuj usunięte rekordy w osobnej tabeli i korzystaj z łączenia, bo byłoby lepiej. Poddałem tę sugestię testowi, ale przynajmniej na pozór dodatkowy stół i łączenie wyglądają na droższe niż używanie flagi.

Wstępne badanie

mam skonfigurować ten test.

Dwie tabele, przykłady i usunięte przykłady. Dodałem nieklastrowany indeks do kolumny IsDeleted.

Zrobiłam trzy testy, ładowanie milionów płyt z następującymi usunięte/non usuniętych proporcjach:

  • usunięte/NonDeleted
  • 50/50
  • 10/90
  • 1/99

Wyniki - 50/50 50 50

Wyniki - 10/90 10 90

Wyniki - 1/99 enter image description here

skryptów bazy danych, w celach informacyjnych, przykładowo DeletedExample i indeks dla 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 

Odpowiedz

8

Numery zostały wydają się wskazywać, że my initial impression była prawidłowa: jeśli najczęstszych zapytań na tej bazy danych jest filtrowanie na IsDeleted = 0, to wydajność będzie lepsza z prostego bitu flagi, zwłaszcza jeśli się mądrego wykorzystania indeksów.

Jeśli często poszukujesz osobno danych usuniętych i nie usuniętych, możesz zauważyć wzrost wydajności dzięki posiadaniu tabeli dla usuniętych elementów i innej dla nie przywróconych elementów, z identycznymi polami. Jednak denormalizacja danych w taki sposób rzadko jest dobrym pomysłem, ponieważ najczęściej kosztuje cię o wiele więcej kosztów utrzymania kodu, niż zwiększy wydajność.

+2

Dobra odpowiedź. Rozważ także użycie filtrowanych indeksów.Jeśli zapytanie dotyczy tabeli Przykład tylko w kolumnie 1, gdy rekordy nie zostaną usunięte, indeks Kolumna1 "WHERE IsDelete = 0". –

1

I nie jestem ekspertem od SQL, ale moim zdaniem wszystko zależy od częstotliwości korzystania z bazy danych. Jeśli baza danych jest dostępna dla dużej liczby użytkowników i musi być wydajna, użycie osobnej tabeli isDeleted będzie dobre. Lepszą opcją byłoby użycie flagi w czasie produkcji, a jako część konserwacji dziennej/tygodniowej/miesięcznej można przenieść wszystkie usunięte z miękkiego rekordu do tabeli isDeleted i wyczyścić tabelę produkcyjną miękkich usuniętych rekordów. Połączenie obu opcji będzie dobre.