Как создать SQL-db с отменой повтора?
Я пытаюсь выяснить, как создавать таблицы БД для Undo-Redo.
Представьте, что у вас есть таблица задач со следующей структурой:
id <int>
title <varchar>
memo <string>
date_added <datetime>
date_due <datetime>
Теперь предположим, что за несколько дней и несколько входов в систему произошло несколько изменений; но пользователь хочет вернуться к одной из версий.
- Будет ли у вас отдельная таблица, отслеживающая изменения, или - попытаетесь ли вы сохранить изменения в таблице задач (строки "призрак" из-за отсутствия лучшего термина)?
- Вы будете отслеживать все столбцы или только те, которые меняются каждый раз?
Если это имеет значение, я использую MySQL. Кроме того, если это имеет значение, я хотел бы показать историю (ala Photoshop) и разрешить пользователю переключаться на любую версию.
Бонусный вопрос: вы сохранили бы целую ячейку memo
при изменении или попытаетесь ли вы сохранить только дельта? Причина, о которой я прошу, состоит в том, что ячейка memo
может быть большой, и только одно слово или символ могут быть изменены в каждой ревизии. Конечно, сохранение дельта потребует разбора, но если отскоки не ожидаются очень часто, не лучше ли экономить место, а не время обработки?
Благодарим вас за помощь.
Ответы
Ответ 1
Я бы создал таблицу History для вашей таблицы задач. Такая же структура, как задачи + новое поле с именем previousId. Это будет содержать предыдущий идентификатор изменения, поэтому вы можете вернуться вперед через разные изменения (отменить/повторить).
Почему новая таблица истории? По простой причине: не перегружайте таблицу задач теми вещами, для которых она не предназначена.
Как и в пространстве, в Истории вместо Memo используйте двоичный формат и запишите содержимое текста, который вы хотите сохранить. Не пытайтесь обнаружить изменения. Вы столкнетесь с ошибкой кода, который приведет к разочарованию и впустую времени...
Оптимизация:
Еще лучше, вы можете хранить только три столбца в таблице "История":
1. taskId (внешний ключ к задачам)
2. data - двоичное поле. Перед сохранением в таблице "История" создайте строку XML, содержащую только те поля, которые были изменены.
3. previousId (поможет сохранить очередь изменений и разрешить навигацию вперед и назад)
Что касается поля данных, создайте XML-строку следующим образом:
<task>
<title>Title was changed</title>
<date_added>2011-03-26 01:29:22<date_added>
</task>
В основном это скажет вам, что на этот раз вы изменили только заголовок и поля date_added.
После того, как строка XML будет построена, просто запишите ее, если хотите, и сохраните ее в поле данных таблицы истории.
XML также обеспечит гибкость. Если вы добавляете/удаляете поле в таблице задач, вам также не нужно обновлять таблицу "История". Таким образом, структура таблицы задач и таблицы "История" разделены, поэтому вам не нужно обновлять две таблицы каждый раз.
PS: не забудьте добавить некоторые индексы, чтобы быстро перемещаться по таблице истории. Поля для индексирования: taskId и previousId, поскольку вам понадобятся быстрые запросы к этой таблице.
Надеюсь, что это поможет.
Ответ 2
Когда я делаю подобные вещи с использованием SQL, я всегда использую вторую таблицу для истории изменений. Это предотвращает чрезмерную загрузку основной таблицы с версиями. Обоснование заключается в том, что получение текущей записи происходит почти в 100% случаев, просмотр истории и откат (отмена) очень редки.
Если у вас есть только один UNDO или история, то отслеживание в таблице, вероятно, отлично.
Если вы хотите сохранить дельта или всю ячейку, зависит от ожидаемого роста/использования. Если вам удобно создавать логику для управления дельтами, это сэкономит вам пространство. Если что-то действительно не создает новые версии, которые я бы не начинал с этого, (применяя YAGNI)
Ответ 3
Возможно, вам захочется сжать ревизии в форме дельта, но вы все равно должны иметь текущую версию для быстрого извлечения.
Однако для более старых и новых дельт требуется много обработки, если у вас нет дельта-дельта. Для более старых дельт требуется переработка каждый раз, когда что-то меняется. Таким образом, дельта обычно не дает вам много преимуществ, но имеет большую сложность.
Последнее, что я проверил, несколько лет назад, MediaWiki, программное обеспечение, находящееся за Википедией, хранит полные тексты и предоставляет некоторые средства сжатия более старые версии с gzip для экономии места и выделенной таблицы archive
для удаленных версий/страниц.
На их веб-сайте есть ER-схема их макета базы данных, которая может вам пригодиться.