Попытка создать столбец, который должен суммировать значения из другой таблицы - PullRequest
1 голос
/ 08 февраля 2010

извините, если название не очень понятно. Я сейчас попробую объяснить:

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

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

Ответы [ 4 ]

1 голос
/ 08 февраля 2010

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

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

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

1 голос
/ 08 февраля 2010

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

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

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

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

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

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

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

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

...