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.
14 answers
Możesz wykonać wszystkie zapytania w widoku zawierającym klauzulę WHERE IS_DELETED='0'
.
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
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).
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.
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
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!)?
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:
- create user (login=JOE)
- soft-delete (Ustaw usuniętą kolumnę na non-null.)
- (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)
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
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.deleted
=0
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
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.
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...
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
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
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
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