Jaki jest najlepszy sposób na wdrożenie miękkiego usuwania?

W tej chwili pracujemy nad projektem i musimy zaimplementować miękkie usuwanie dla większości użytkowników (role użytkowników). Zdecydowaliśmy się dodać pole" is_deleted='0' "do każdej tabeli w bazie danych i ustawić je na "1", jeśli określone role użytkowników nacisną przycisk Usuń na określonym rekordzie.

Dla przyszłej konserwacji, każde zapytanie SELECT musi upewnić się, że nie zawiera rekordów, w których is_deleted='1'.

Czy jest lepsze rozwiązanie dla implementacji soft deletion?

Update: Należy również zauważyć, że mamy bazę danych audytu, która śledzi zmiany (pole, Stara wartość, nowa wartość, Czas, Użytkownik, ip) do wszystkich tabel/pól w bazie danych aplikacji.

Author: Brian Tompsett - 汤莱恩, 2008-09-16

14 answers

Możesz wykonać wszystkie zapytania w widoku zawierającym klauzulę WHERE IS_DELETED='0'.

 42
Author: David J. Sokol,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 00:49:19

Skłaniałbym się ku "Rails way" z kolumną deleted_at, która zawiera datę, kiedy miało miejsce usunięcie. Następnie otrzymasz trochę darmowych metadanych o usunięciu. Dla Twojego SELECT wystarczy pobrać wiersze, w których deleted_at jest NULL

 78
Author: ctcherry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 00:50:42

Posiadanie kolumny is_deleted jest dość dobrym podejściem. Jeśli jest w Oracle, aby jeszcze bardziej zwiększyć wydajność, polecam partycjonowanie tabeli poprzez utworzenie partycji listowej na kolumnie is_deleted. Następnie usunięte i nieusunięte wiersze będą fizycznie znajdować się na różnych partycjach, chociaż dla ciebie będą przezroczyste.

W rezultacie, jeśli wpiszesz zapytanie typu

SELECT * from table_name where is_deleted = 1

Następnie Oracle wykona 'przycinanie partycji' i zajrzy tylko do odpowiedniej partycji. Wewnętrznie a partycja jest inną tabelą, ale jest przezroczysta dla użytkownika: będziesz mógł wybrać całą tabelę bez względu na to, czy jest podzielona na partycje, czy nie. Ale Oracle będzie w stanie odpytywać tylko to, czego potrzebuje. Na przykład, załóżmy, że masz 1000 wierszy z is_deleted=0 i 100000 wierszy z IS_DELETED=1, i partycji tabeli na IS_DELETED. Teraz jeśli włączysz warunek

WHERE ... AND IS_DELETED=0

Wtedy Oracle skanuje tylko partycję z 1000 wierszami. Gdyby stół nie partycjonowany, musiałby skanować 101000 wierszy(obie partycje).

 19
Author: Sergey Stadnik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-04 05:44:52

Najlepsza odpowiedź, niestety, zależy od tego, co próbujesz osiągnąć z miękkimi usunięciami i bazą danych, w której to implementujesz.

W SQL Server najlepszym rozwiązaniem byłoby użycie kolumny deleted_on/deleted_at z typem SMALLDATETIME lub DATETIME (w zależności od potrzebnej ziarnistości) i uczynienie tej kolumny nullable. W SQL Server dane nagłówka wiersza zawierają maskę bitową NULL dla każdej z kolumn w tabeli, więc nieznacznie szybciej jest wykonać Jest NULL lub nie jest NULL niż jest do sprawdzenia wartości przechowywanej w kolumnie.

Jeśli masz dużą ilość danych, będziesz chciał przyjrzeć się partycjonowaniu danych, albo przez samą bazę danych, albo przez dwie oddzielne tabele (np. produkty i ProductHistory) lub przez zindeksowany widok.

Zazwyczaj unikam pól flag, takich jak is_deleted, is_archive, itp., Ponieważ Mają one tylko jedno znaczenie. Pole nullable deleted_at, archived_at zapewnia dodatkowy poziom znaczenie dla siebie i tego, kto dziedziczy Twoje podanie. I unikam pól bitmask, takich jak plaga, ponieważ wymagają one zrozumienia, jak bitmask został zbudowany, aby zrozumieć jakiekolwiek znaczenie.

 13
Author: Jeremiah Peschka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 12:47:20

Jeśli tabela jest duża i wydajność jest problemem, zawsze możesz przenieść "usunięte" rekordy do innej tabeli, która zawiera dodatkowe informacje, takie jak czas usunięcia, kto usunął rekord, itp

W ten sposób nie musisz dodawać kolejnej kolumny do głównej tabeli

 11
Author: Jiaaro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 00:49:49

To zależy od tego, jakich informacji potrzebujesz i jakie przepływy pracy chcesz wspierać.

Czy chcesz być w stanie:

  • wiesz, jakie informacje tam były (zanim zostały usunięte)?
  • wiesz, kiedy został usunięty?
  • Wiesz, kto to usunął? Wiesz, w jakim charakterze działali, kiedy to usuwali?
  • BYĆ w stanie usunąć rekord?
  • BYĆ w stanie stwierdzić, kiedy został usunięty?
  • itd.

Jeśli rekord został usunięty i nie-deleted cztery razy, czy wystarczy, aby wiedzieć, że jest obecnie w stanie nie-deleted, czy chcesz być w stanie powiedzieć, co stało się w międzyczasie (w tym wszelkie zmiany między kolejnymi usunięciami!)?

 9
Author: Daniel Fortunov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 00:57:24

Ostrożnie z usuniętymi plikami powodującymi naruszenia ograniczeń unikalności. Jeśli DB ma kolumny z unikalnymi ograniczeniami, należy uważać, aby wcześniejsze usunięte rekordy nie uniemożliwiały odtworzenia rekordu.

Myśl o cyklu:

  1. create user (login=JOE)
  2. soft-delete (Ustaw usuniętą kolumnę na non-null.)
  3. (re) Utwórz użytkownika (login=JOE). Błąd. LOGIN=JOE jest już zajęty

Second create results in a constraint violation ponieważ login = JOE jest już w soft-usuniętym wierszu.

Niektóre techniki: 1. Przenieś usunięty rekord do nowej tabeli. 2. Utwórz ograniczenie unikalności w kolumnie login and deleted_at timestamp

Moim zdaniem +1 za przejście do nowej tabeli. Its take lots of dyscyplina, aby utrzymać *i delete_at = NULL * we wszystkich swoich queries (for all of your developers)

 6
Author: Andy Rappaport,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-04 14:16:18

Na pewno będziesz miał lepszą wydajność, jeśli przeniesiesz usunięte DANE do innej tabeli, jak powiedział Jim, a także będziesz mieć zapis, kiedy zostały usunięte, dlaczego i przez kogo.

Dodawanie where deleted=0 do wszystkich zapytań znacznie je spowolni i utrudni korzystanie z dowolnego z indeksów, które możesz mieć na stole. W miarę możliwości unikaj "FLAG" w swoich tabelach.

 3
Author: UltimateBrent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 01:33:11

Coś, co używam w projektach jest statusInd tinyint nie null domyślna kolumna 0 użycie statusInd jako maski bitowej pozwala mi na zarządzanie danymi (usuwanie, archiwizowanie, replikowanie, przywracanie itp.). Korzystając z tego w widokach, mogę następnie wykonać dystrybucję danych, publikację itp. dla zużywających się aplikacji. Jeśli wydajność jest problemem dotyczącym widoków, użyj małych tabel faktów, aby wesprzeć te informacje, opuszczając fakt, opuszczając relację i pozwalając na skalowane usuwanie.

Dobrze skaluje i czy data centric utrzymuje ślad danych dość mały-klucz dla 350gb + dbs z problemami w czasie rzeczywistym. Korzystanie z alternatyw, tabel, wyzwalaczy ma pewne narzuty, które w zależności od potrzeby mogą lub nie mogą działać dla Ciebie.

Audyty związane z SOX mogą wymagać więcej niż pola, aby pomóc w Twoim przypadku, ale to może pomóc. Enjoy

 1
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 05:31:44

Nie wspominasz jaki produkt, ale SQL Server 2008 i postgresql (i inne, jestem pewien) pozwalają na tworzenie filtrowanych indeksów, dzięki czemu można utworzyć indeks pokrycia, gdzie is_deleted=0, łagodząc niektóre negatywy tego konkretnego podejścia.

 1
Author: Andy Irving,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 14:15:30

Wolę zachować kolumnę statusu, więc mogę jej używać do kilku różnych konfiguracji, np. published, private, deleted, needsAproval...

 0
Author: UnkwnTech,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 01:09:30

Użyj widoku, funkcji lub procedury, które sprawdzają is_deleted=0, tzn. nie wybieraj bezpośrednio w tabeli, jeśli tabela będzie musiała zmienić się później z innych powodów

I indeksuje kolumnę is_deleted dla większych tabel

Ponieważ masz już ścieżkę audytu, śledzenie daty usunięcia jest zbędne

 0
Author: Steven A. Lowe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 03:25:48

Utwórz inny schemat i przyznaj go na swoim schemacie danych. Zaimplementuj VPD na swoim nowym schemacie tak, aby każde zapytanie miało predykat pozwalający na wybór nieusuniętego wiersza tylko do niego dołączonego. http://download.oracle.com/docs/cd/E11882_01/server.112/e16508/cmntopc.htm#CNCPT62345

 0
Author: adsm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-27 11:15:50

@AdditionalCriteria("to.status 'deleted'")

Umieść to na swoim @ entity

Http://wiki.eclipse.org/EclipseLink/Examples/JPA/SoftDelete

 0
Author: Kalpesh Soni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-21 14:26:36