Каков наилучший способ реализовать мягкое удаление?

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

Вопрос

В данный момент мы работаем над проектом, и нам необходимо внедрить мягкое удаление для большинства пользователей (ролей пользователей).Мы решили добавить поле "is_deleted='0'" в каждую таблицу базы данных и установить для него значение "1", если определенные роли пользователей нажимают кнопку удаления в определенной записи.

Для дальнейшего обслуживания теперь каждый запрос SELECT должен будет убедиться, что они не включают записи, где is_deleted='1'.

Есть ли лучшее решение для реализации мягкого удаления?

Обновить:Я должен также отметить, что у нас есть база данных аудита, которая отслеживает изменения (поле, старое значение, новое значение, время, пользователь, ip) во всех таблицах / полях в базе данных приложения.

Это было полезно?

Решение

Вы могли бы выполнять все свои запросы к представлению, содержащему WHERE IS_DELETED='0' оговорка.

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

Я бы склонялся к "Рельсовому пути" с deleted_at столбец, содержащий дата и время, когда произошло удаление.Затем вы получаете немного бесплатных метаданных об удалении.Для вашего SELECT просто получите строки WHERE deleted_at IS NULL

Имея is_deleted колонка - это достаточно хороший подход.Если это в Oracle, то для дальнейшего повышения производительности я бы рекомендовал разбить таблицу на разделы, создав раздел списка на is_deleted колонна.Тогда удаленные и не удаленные строки физически будут находиться в разных разделах, хотя для вас это будет прозрачно.

В результате, если вы введете запрос типа

SELECT * FROM table_name WHERE is_deleted = 1

затем Oracle выполнит "обрезку раздела" и просмотрит только соответствующий раздел.Внутренне раздел представляет собой другую таблицу, но он прозрачен для вас как пользователя:вы сможете выбирать по всей таблице, независимо от того, разбита она на разделы или нет.Но Oracle сможет запрашивать ТОЛЬКО тот раздел, который ему нужен.Например, давайте предположим, что у вас есть 1000 строк с is_deleted = 0 и 100000 строк с is_deleted = 1, и вы разбиваете таблицу на is_deleted.Теперь, если вы включите условие

WHERE ... AND IS_DELETED=0

тогда Oracle будет сканировать раздел ТОЛЬКО с 1000 строками.Если бы таблица не была разбита на разделы, ей пришлось бы просканировать 101000 строк (оба раздела).

если таблица большая и производительность является проблемой, вы всегда можете переместить "удаленные" записи в другую таблицу, в которой есть дополнительная информация, такая как время удаления, кто удалил запись и т. Д

таким образом, вам не нужно добавлять еще один столбец в вашу основную таблицу

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

В SQL Server лучшим решением было бы использовать столбец deleted_on / deleted_at с типом SMALLDATETIME или DATETIME (в зависимости от необходимой детализации) и сделать этот столбец обнуляемым.В SQL Server данные заголовка строки содержат битовую маску NULL для каждого из столбцов в таблице, поэтому выполнение IS NULL или NOT NOT NULL немного быстрее, чем проверка значения, хранящегося в столбце.

Если у вас большой объем данных, вам захочется изучить возможность разделения ваших данных либо через саму базу данных, либо через две отдельные таблицы (напримерProducts и ProductHistory) или через индексированное представление.

Обычно я избегаю полей флага, таких как is_deleted, is_archive и т.д., потому что они несут только один смысл.Обнуляемое поле deleted_at, archived_at предоставляет дополнительный уровень значимости вам и тому, кто унаследует ваше приложение.И я избегаю полей битовой маски, подобных чуме, поскольку они требуют понимания того, как была создана битовая маска, чтобы понять какой-либо смысл.

Это зависит от того, какая информация вам нужна и какие рабочие процессы вы хотите поддерживать.

Вы хотите иметь возможность:

  • знаете, какая информация там была (до того, как она была удалена)?
  • знаете, когда оно было удалено?
  • знаете, кто его удалил?
  • знаете, в каком качестве они действовали, когда удаляли его?
  • сможете отменить удаление записи?
  • сможете ли вы определить, когда оно было удалено?
  • и т.д.

Если запись удалялась и не удалялась четыре раза, достаточно ли вам знать, что в данный момент она находится в не удаленном состоянии, или вы хотите иметь возможность сказать, что произошло за это время (включая любые правки между последовательными удалениями!)?

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

Подумайте о цикле:

  1. создать пользователя (логин=JOE)
  2. автоматическое удаление (установите для удаленного столбца значение, отличное от нуля.)
  3. (повторно) создайте пользователя (login=JOE).ОШИБКА.ЛОГИН= ДЖО уже занят

Второе создание приводит к нарушению ограничения, потому что login=JOE уже находится в строке с программным удалением.

Некоторые методы:1.Переместите удаленную запись в новую таблицу.2.Установите ограничение уникальности в столбце login и deleted_at timestamp

Мое личное мнение - +1 за переход на новую таблицу.Требуется большая дисциплина для поддержания *И delete_at = NULL * во всех ваших запросах (для всех ваших разработчиков)

У вас определенно повысится производительность, если вы переместите удаленные данные в другую таблицу, как сказал Джим, а также получите запись о том, когда они были удалены, почему и кем.

Добавление where deleted=0 выполнение всех ваших запросов значительно замедлит их выполнение и затруднит использование любого из индексов, которые могут быть у вас в таблице.По возможности избегайте наличия "флагов" в ваших таблицах.

Что-то, что я использую в проектах, - это столбец statusInd tinyint not null по умолчанию 0 использование statusInd в качестве битовой маски позволяет мне выполнять управление данными (удалять, архивировать, реплицировать, восстанавливать и т.д.).Используя это в представлениях, я могу затем выполнять распределение данных, публикацию и т.д. Для приложений-потребителей.Если производительность вызывает беспокойство в отношении представлений, используйте небольшие таблицы фактов для поддержки этой информации, отбрасывая факт, отбрасывая связь и допуская масштабируемые удаления.

Хорошо масштабируется и ориентирован на данные, сохраняя объем данных довольно небольшим - ключ для 350gb + dbs с функциями реального времени.Использование альтернатив, таблиц, триггеров сопряжено с некоторыми накладными расходами, которые в зависимости от необходимости могут работать, а могут и не работать для вас.

Для аудита, связанного с SOX, в вашем случае может потребоваться нечто большее, чем просто поле, но это может помочь.Наслаждайтесь

вы не упоминаете, какой продукт, но SQL Server 2008 и postgresql (и другие, я уверен) позволяют вам создавать отфильтрованные индексы, поэтому вы могли бы создать покрывающий индекс, где is_deleted= 0, смягчая некоторые недостатки этого конкретного подхода.

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

используйте представление, функцию или процедуру, которая проверяет is_deleted=0, т.е.не выбирайте непосредственно в таблице на случай, если таблицу потребуется изменить позже по другим причинам

и проиндексируйте столбец is_deleted для таблиц большего размера

поскольку у вас уже есть журнал аудита, отслеживание даты удаления является излишним

Создайте другую схему и предоставьте все это вашей схеме данных.Внедрите VPD в вашу новую схему, чтобы каждый запрос имел предикат, разрешающий выбор только добавленной к нему не удаленной строки.http://download.oracle.com/docs/cd/E11882_01/server.112/e16508/cmntopc.htm#CNCPT62345

@AdditionalCriteria("этот.status <> "удалено"")

поместите это поверх вашего @entity

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

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