Обработка изменений в Oracle

У меня есть таблица сказать:

CREATE TABLE "DataNode" (
   "ID" NUMBER(7,0),
   "TYPE" NUMBER(7,0),
   "NAME" VARCHAR2(100),
   "STATUS" NUMBER(7,0),
   "REVISION" NUMBER(4,0),
   "MODIFIEDAT" DATE
 );

 CREATE TABLE "DataNode_Revisions" (
   "ID" NUMBER(7,0),
   "NODEID" NUMBER(7,0),
   "TYPE" NUMBER(7,0),
   "NAME" VARCHAR2(100),
   "STATUS" NUMBER(7,0),
   "REVISION" NUMBER(4,0),
   "MODIFIEDAT" DATE
 ) COMPRESS;

Итак, у меня есть эти две таблицы. Я делаю все свои чтения из "DataNode", и когда происходит изменение, я записываю текущую запись в "DataNode_Revisions", а затем изменяю свою существующую запись "DataNode". Имеет смысл?

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

"DataNode" постоянно читается многими пользователями. Тем не менее, очень мало записей происходит. "DataNode_Revisions" только для чтения из иногда. Я просто беспокоюсь о том, чтобы поддерживать так много таблиц. "DataNode" - одна из 25 таблиц, очень похожих на эту.

4 ответа

Решение

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

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

CREATE INDEX idx_current_ids
    ON DataNode( (CASE WHEN expiration_date IS NULL THEN id ELSE null END) );

который будет использоваться в запросе, как

SELECT *
  FROM DataNode
 WHERE (CASE WHEN expiration_date IS NULL THEN id ELSE null END) = <<some id>>

Очевидно, что вы, вероятно, захотите создать представление с таким условием, а не переписывать его каждый раз, когда вам нужна текущая строка, т.е.

CREATE VIEW CurrentDataNode
AS
SELECT (CASE WHEN expiration_date IS NULL THEN id ELSE null END) id,
       type,
       name,
       status
  FROM DataNode;

SELECT *
  FROM CurrentDataNode
 WHERE id = <<some value>>

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

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

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

Это будет зависеть от приложения. Если вы используете 11g, возможно, вы захотите взглянуть на новый архив данных Flashback. Я только начинаю смотреть на это, чтобы сохранить историю всех наших финансовых и других важных данных.

У вас есть несколько вариантов. Какое бизнес-требование заставляет вас отслеживать изменения данных?

  • если вам нужно сохранить изменения только в течение некоторого "короткого" периода времени, вы можете прочитать данные из UNDO, используя запрос флешбека. select * from table from timestamp (bla);

  • если вам нужно хранить эту информацию в течение длительного времени, посмотрите на функцию под названием Oracle Total Recall. Он делает то же самое, что Flashback Query, но сохраняет изменения на неопределенный срок.

  • если вам нужно что-то более простое, не заставляйте приложение вставлять "старую" версию строк. Используйте триггер, который заполняет данные.

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

Другие вопросы по тегам