Как избежать добавления полей времени в таблицы?
У меня есть вопрос относительно двух дополнительных столбцов (timeCreated, timeLastUpdated) для каждой записи, которую мы видим во многих решениях. Мой вопрос: есть ли лучшая альтернатива?
Сценарий: у вас есть огромная БД (с точки зрения таблиц, а не записей), а затем приходит клиент и просит добавить "временную привязку" к 80% ваших таблиц.
Я считаю, что это можно сделать, используя отдельную таблицу (TIMESTAMPS). В этой таблице в дополнение к очевидному столбцу временной метки указывается имя таблицы и первичный ключ для обновляемой таблицы. (Я предполагаю, что для большинства ваших таблиц вы используете int как первичный ключ, но имя таблицы, скорее всего, должно быть строкой).
Чтобы представить это, предположим, этот базовый сценарий. У нас было бы две таблицы:
ОПЛАТА: - (ваши обычные записи)
TIMESTAMP: - {текущая временная метка} + { TABLE_UPDATED
, id_of_entry_updated
, timestamp_type
}
Обратите внимание, что в этом дизайне вам не нужны эти два "дополнительных" столбца в вашем собственном объекте оплаты (который, кстати, может сделать это через ваше решение ORM), поскольку теперь вы индексируете TABLE_UPDATED
и id_of_entry_updated
. Кроме того, timestamp_type
сообщит вам, есть ли запись для вставки (например, "1" ), обновление (например, "2" ) и все, что вы можете добавить, например "удаление".
Я хотел бы знать, что вы думаете об этом дизайне. Меня больше всего интересуют лучшие практики, что работает и масштабируется с течением времени. Ссылки, ссылки, записи в блогах более чем приветствуются. Я знаю, по крайней мере, один патент (в ожидании), который пытается решить эту проблему, но, похоже, детали не являются общедоступными в настоящее время.
Cheers,
Эдуардо
Ответы
Ответ 1
Пока вы на нем, также запишите пользователя, внесшего изменения.
Недостаток с дизайном отдельной таблицы (в дополнение к производительности соединения, выделенный другими) заключается в том, что он делает предположение, что каждая таблица имеет столбец идентификатора для ключа. Это не всегда так.
Если вы используете SQL Server, новая версия 2008 поддерживает то, что они называют Change Data Capture
, что должно забрать большую боль, о которой вы говорите. Я думаю, что Oracle может иметь что-то подобное.
Обновление: очевидно, Oracle называет его тем же, что и SQL Server. Вернее, SQL Server называет это тем же, что и Oracle, поскольку реализация Oracle была первой;)
http://www.oracle.com/technology/oramag/oracle/03-nov/o63tech_bi.html
Ответ 2
Я использовал конструкцию, в которой каждая проверяемая таблица имела две таблицы:
create table NAME (
name_id int,
first_name varchar
last_name varchar
-- any other table/column constraints
)
create table NAME_AUDIT (
name_audit_id int
name_id int
first_name varchar
last_name varchar
update_type char(1) -- 'U', 'D', 'C'
update_date datetime
-- no table constraints really, outside of name_audit_id as PK
)
Создается триггер базы данных, который заполняет NAME_AUDIT
каждый раз, когда что-либо делается с NAME
. Таким образом, у вас есть запись каждого изменения, внесенного в таблицу, и когда. Приложение не знает об этом, так как оно поддерживается триггером базы данных.
Он работает достаточно хорошо и не требует каких-либо изменений для кода приложения для реализации.
Ответ 3
Мне кажется, я предпочитаю добавлять временные метки к отдельным таблицам. Присоединение к таблице timestamp на составном ключе - одна из которых является строкой - будет медленнее, и если у вас будет большой объем данных, это будет в конечном итоге реальной проблемой.
Кроме того, много времени, когда вы смотрите на отметки времени, это когда вы отлаживаете проблему в своем приложении, и вам понадобятся данные прямо там, а не всегда, чтобы присоединиться к другой таблице.
Ответ 4
Преимущество метода, который вы предлагаете, заключается в том, что он дает вам возможность добавлять другие поля в таблицу TIMESTAMP, например, отслеживать пользователя, внесшего изменения. Вы также можете отслеживать изменения в чувствительных полях, например, кто пересматривал этот контракт?
Изменения записи журнала в отдельном файле означают, что вы можете показать несколько изменений в записи, например:
mm/dd/yy hh: mm: ss Добавлено XXX
mm/dd/yy hh: mm: ss Поле ЦЕНА Изменено XXX,
mm/dd/yy hh: mm: ss Запись удалена XXX
Одним из недостатков является дополнительный код, который будет выполнять вставки в вашу таблицу TIMESTAMPS, чтобы отразить изменения в основных таблицах.
Ответ 5
Если вы настроили материал временной метки для запуска триггеров, можно выполнить регистрацию любого действия, которое может установить триггер (Чтение?). Также могут быть некоторые преимущества блокировки.
(Возьмите все с солью, я не DBA или SQL-гуру)
Ответ 6
Да, мне нравится этот дизайн и используйте его с некоторыми системами. Обычно, некоторый вариант:
LogID int
Action varchar(1) -- ADDED (A)/UPDATED (U)/DELETED (D)
UserID varchar(20) -- UserID of culprit :)
Timestamp datetime -- Date/Time
TableName varchar(50) -- Table Name or Stored Procedure ran
UniqueID int -- Unique ID of record acted upon
Notes varchar(1000) -- Other notes Stored Procedure or Application may provide
Ответ 7
Один кошмар с вашим дизайном заключается в том, что каждая отдельная вставка, обновление или удаление должны были бы ударить по этой таблице. Это может вызвать серьезные проблемы с производительностью и блокировкой. Плохая идея обобщить таблицу, подобную этой (не только для временных меток). Было бы также кошмаром, чтобы получить данные из.
Если ваш код сломается на уровне GUI, добавив поля, которые вы не хотите видеть, вы неправильно записываете код в свой графический интерфейс, который должен указывать только минимальное количество столбцов, которые вам нужны, и никогда не выбирайте *.
Ответ 8
Я думаю, что дополнительные соединения, которые вам придется выполнять, чтобы получить Timestamps, будут небольшим ударом по производительности и болью в шее. Кроме этого, я не вижу проблем.
Ответ 9
Мы сделали именно то, что вы сделали. Это отлично подходит для объектной модели и возможности добавления новых марок и разных типов штампов в нашу модель с минимальным кодом. Мы также отслеживали пользователя, внесшего изменения, и большая часть нашей логики была в значительной степени основана на этих марках. Это было очень хорошо.
Один недостаток - это отчетность и/или отображение множества разных марок на экране. Если вы делаете это так, как мы это делали, это вызвало много стыков. Кроме того, задние окончание изменений было болью.
Ответ 10
Наше решение состоит в том, чтобы сохранить таблицу "Транзакция" в дополнение к нашей таблице "Сессия". Команды UPDATE, INSERT и DELETE управляются через объект "Транзакция", и каждая из этих инструкций SQL хранится в таблице "Транзакция", как только она была успешно выполнена в базе данных. В этой таблице "Транзакция" есть другие поля, такие как transactiontType (I для INSERT, D для DELETE, U для UPDATE), transactionDateTime и т.д. И внешний ключ "sessionId", сообщая нам, наконец, кто отправил инструкцию. Даже через некоторый код можно определить, кто и что (когда Гас создал запись в понедельник, Тим изменил Стоимость единицы во вторник, Лиз добавила дополнительную скидку в четверг и т.д.).
Плюсы для этого решения:
- вы можете сказать "кто и когда" и показать его своим пользователям! (вам понадобится код для анализа операторов SQL)
- Если ваши данные реплицируются и репликация завершается с ошибкой, вы можете перестроить свою базу данных через эту таблицу.
Минусы
- 100 000 обновлений данных в месяц означают 100 000 записей в Tbl_Transaction
- Наконец, эта таблица имеет тенденцию быть 99% объема вашей базы данных
Наш выбор: все записи старше 90 дней автоматически удаляются каждое утро.
Ответ 11
Филипп,
Не просто удаляйте те, которые старше 90 дней, перенесите их сначала в отдельный БД или напишите их в текстовый файл, сделайте что-то, чтобы их сохранить, просто переместите их из основной производственной БД.
Если когда-либо дойдет до него, чаще всего это случай "с наибольшим количеством документов"!