2010-02-08 5 views
1

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

У меня есть две таблицы: таблица A и таблица B. Отношение между ними - одно (для таблицы A) для многих (для таблицы B). Итак, это что-то вроде ситуации мастер-детали. У меня есть столбец «Сумма» в таблице B, который, очевидно, десятичный, и столбец «TotalAmount» в таблице A. Я пытаюсь выяснить, как сохранить значение в таблице A в актуальном состоянии. Мое предложение состоит в том, чтобы сделать представление, основанное на таблице A, с агрегированным запросом, подсчитывающим суммы из таблицы B. Конечно, с соответствующими индексами ... Но мой партнер по команде предлагает обновить значение в таблице A каждый раз, когда мы что-то меняем в таблице B из нашего приложения. Интересно, что будет лучшим решением здесь? Может быть, третий вариант?

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

ответ

1

Я вижу несколько вариантов:

  1. Используйте триггер вставки на таблицу В и делать обновление таблицы А, как ваш друг говорит. Это позволит сохранить таблицу B как можно более актуальной.
  2. Запланируйте задание, которое обновляет таблицу A каждые x минут (x = что имеет смысл для вашего приложения).
  3. При обновлении таблицы B выполните обновление таблицы A в логике приложения. Это может не сработать, если вы обновите таблицу B во многих местах.
+0

Вариант 2 здесь не применим, поскольку мы должны быть всегда в курсе событий. Но вариант 1 звучит разумно. – anthares

1

Если у вас есть одно место в приложении, где вы вставить новые строки в таблицу В, то самое простое решение отправить UPDATE A set TotalAmount=TotalAmount + ? where ID = ? и передать значения, которые вы просто использовали для вставки в B. Убедитесь, что вы заключаете оба запроса (вставка и обновление) в транзакции, так что либо происходит, либо нет.

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

Вид другой вариант, но это может вызвать проблемы с производительностью во время выбора, которые вам трудно решить. Вместо этого попробуйте «материализованное представление» или «вычисленный столбец» (но это может вызвать проблемы с производительностью при вставке/удалении столбцов).

1

Если это значение сильно изменится, вам лучше использовать представление: это определенно более безопасная реализация. Но даже лучше использовать триггеры (если ваша база данных поддерживает их.)

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

  • Ваша база данных должна заботиться о кешировании, поэтому это, вероятно, не будет проблемой.
  • Если это так, вы можете добавить эту функцию на более позднем этапе - таким образом, вы можете убедиться, что ваше приложение работает в противном случае и будет иметь много более легкую отладку этого столбца кэша.
0

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

Однако, в общем, предпочтительнее просматривать триггеры - таким образом вам не нужно беспокоиться о сохранении ценности вообще. Профиль, чтобы определить, является ли производительность проблемой. В Postgres я считаю, что вы даже можете создать индекс для вычисленных значений, поэтому базе данных не нужно было бы смотреть на таблицу подробностей.

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

Смежные вопросы