Таблица надгробий против удаленного флага в сценариях синхронизации и мягкого удаления базы данных


17

Мне нужно отслеживать удаленные элементы для синхронизации клиентов.

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

Ответы:


17

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

  • Как быстро должно быть удаление?
  • Как быстро должно быть удаление?
  • Как часто будут запрашиваться удаленные данные и будут ли они запрашиваться с данными, которые не были удалены?
  • Насколько быстрыми должны быть запросы удаленных данных?
  • Вам нужно сохранить только удаленные элементы или изменения?
  • Вам нужно, чтобы таблица / индексы первичной таблицы были небольшими?
  • Какие технологии разделения и / или отслеживания изменений доступны на платформе базы данных?
  • Сколько дискового пространства доступно?
  • Будет ли удаление происходить на лету или в пакетных операциях?

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

Ты понял. Могут даже быть случаи, когда предпочтительнее будет другой вариант. Например, если вам нужно, чтобы программные удаления были доступны только в течение 24 часов, в Oracle вы могли бы рассмотреть возможность установки гарантированного времени отмены и последующего использования ретроспективных запросов для просмотра удаленных данных.
— Ли Риффель

5

Может быть, вы должны объединить два метода нарочно. Почему ???

Давайте использовать эту таблицу (MySQL-диалект)

CREATE TABLE mydata
(
    id int not null auto_increment
    firstname varchar(16) not null,
    lastname varchar(16) not null,
    zipcode char(5) not null,
    ...
    deleted tinyint not null default 0
    KEY (deleted,id),
    KEY (deleted,lastname,firstname,id),
    KEY (deleted,zipcode,id),
    KEY (lastname,firstname),
    KEY (zipcode),
    PRIMARY KEY (id)
);

Обратите внимание, что, за исключением PRIMARY KEY, каждому индексу, который вы создаете, должен предшествовать deletedфлаг и заканчиваться на id.

Давайте создадим надгробный стол

CREATE TABLE mytomb SELECT id FROM mydata WHERE 1=2;
ALTER TABLE mytomb ADD PRIMARY KEY (id);

Если у вашей таблицы уже есть deletedфлаг, вы можете заполнить таблицу с надписью

INSERT INTO mytomb SELECT id FROM mydata WHERE deleted = 1;

Хорошо, теперь данные и надгробная плита подготовлены. Как вы выполняете удаление?

Допустим, вы удаляете каждого человека из почтового индекса 07305. Вы бы запустили следующее:

INSERT IGNORE INTO mytomb SELECT id FROM mydata WHERE deleted=0 AND zipcode='07305';
UPDATE mydata SET deleted=1 WHERE deleted=0 AND zipcode='07305';

Хорошо, это выглядит как много накладных расходов в любом случае.

Теперь, вы хотите увидеть все удаленные данные? Вот два разных способа:

  • SELECT * FROM mydata WHERE deleted=1;
  • SELECT B.* FROM mytomb A INNER JOIN mydata B USING (id);

Если число идентификаторов в mytomb превышает 5% от количества строк в mydata, это полное сканирование таблицы. В противном случае выполняется сканирование индекса с поиском для каждой строки. Обратите внимание на любые ориентиры в этом отношении. Поиск объяснения планов.

Теперь, вы хотите увидеть каждого человека в почтовый индекс 07304? Вот два разных способа:

  • SELECT * FROM mydata WHERE deleted=1 AND zipcode='07304';
  • SELECT A.* FROM mydata A LEFT JOIN mytomb B USING (id) WHERE B.id IS NULL AND A.zipcode='07304'

Как насчет массовых удалений? Вот два разных способа:

  • DELETE FROM mydata WHERE deleted=1;
  • DELETE B.* FROM mytomb A INNER JOIN mydata B USING (id); DELETE FROM mytomb;

ВЫВОД

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


Есть ли преимущество в использовании обоих методов на постоянной основе? Или вы предлагаете просто использовать их параллельно для оценки производительности, а затем переходить к одному или другому?
— Джон на все руки
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.