2009-11-07 2 views
0

У меня есть Firebird базу данных, которая, скажем, есть таблицы А и В, которые выглядят так:Database Design вопрос

TableA

TableB's Id | SomeNumber | OtherNumber | ComputedByField    | OtherIntField 
    1    5   200   SomeNumber*OtherNumber   10 
    1    2   70     ...      20 

TableB

Id | Sum      | Sum 
1  Sum of OtherIntFIeld  Sum of ComputedByField 

where TableA'sId = TableB's Id 

Но теперь, когда TableB является из-за этого вычисление становится заселенным (он находится на расстоянии 2 тыс. строк).

Так что мой вопрос: должен ли я отбрасывать поле Table12 computedby и добавлять его прямо в TableB, и когда новые строки таблицы TableA добавляются для изменения соответствующей строки вручную? (Это должно быть быстрее, но мне это не очень нравится)

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

Edit2: Строки вычисляются следующим образом

TABLEB_FIELD_X COMPUTED BY ((
    select SUM(TableA.FieldX) from TableA 
    where TableA.FAT_ID = TableB.ID 
)) 

TABLEB_FIELD_Y COMPUTED BY ((
    select SUM(TableA.FieldY) from TableA 
    where TableA.FAT_ID = TableB.ID 
)) 

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

+0

Это плохо поставленный вопрос, потому что в нем отсутствуют важные детали. Например, как вы рассчитали суммы? – MaD70

ответ

1

Вместо TableB, почему бы вам не создать view? (Предупреждение: Я никогда не использовал Firebird, и я не знаю, насколько хорошо он поддерживает представления).

Такой вид будет что-то вроде:

create view Totals (SumX, SumY) 
      as 
     select SUM(FieldX), SUM(FieldY) 
     from TableA 
    group by ID 

Каждый раз, когда TableA будет изменен, например вид (Totals) будет обновляться автоматически. Порядочная СУБД будет неплохо работать над ее оптимизацией: она будет пересчитывать достаточно из Totals только тогда, когда TableA изменен, в отличие от вашего TableB, который будет пересчитываться каждый раз при запросе (я полагаю, по вашим проблемам с производительностью - чтобы быть уверенным нужно знать внутренние компоненты Firebird).

Totals будет как любой другой стол (но только для чтения); Вы фильтрует информацию с чем-то вроде:

select * from Totals where ID = ... 

PS: Уолтер Митти обратил мое внимание в комментариях ниже, что я предполагал о своем первоначальном решении, то есть, что TableA:

  • должен быть в (по крайней мере) Первая нормальная форма (1NF) - в противном случае у вас нет гарантированных правильных результатов для реляционных операций (nota bene: необходимо знать ваши требования к приложениям и концептуальный/логический дизайн в деталях - что нецелесообразно приобретать на форуме/через indi прямая связь - выявить возможные проблемы в не полностью нормализованном дизайне, например, вставить/удалить/обновить аномалии; a good книга по теории БД избавит вас от головных болей и, к сожалению, таких книг мало);
  • правильно проиндексирован (по крайней мере, на ID).

К сожалению, SQL на основе DBMSes требует таких физических деталей дизайна от пользователей, чтобы иметь достойные выступления, это противоречит тому, что СУБД должна быть хорошо (он имеет всю информацию, необходимую, чтобы сделать хорошая работа автоматически, т.е. владение физическими структурами данных и статистика путей доступа к данным).

+0

Вид должен получить идентификатор в качестве параметра, для которого строки для фильтрации – zz1433

+0

Я не понимаю. Такое представление будет точно таким же, как любая другая таблица (но только для чтения). – MaD70

+0

О, хорошо спасибо, не знал, что – zz1433

0

Я хотел бы использовать триггер на таблицу А, которая обновляет таблицу B с суммой полей после каких-либо вставок/обновлений/удалений в таблице А.

Это будет иметь небольшое дополнительное воздействие на любые операции, происходящие на столе A, но будет более эффективным при запросе таблицы B.

0

Не знаете, почему вы хотите пересчитать всю таблицу при каждом обновлении? Вот что означает ваш код и объяснение.

Лучше всего хранить вычисленное значение как регулярное значение целое или что-то другое. Затем вы можете добавить такие вещи, как индексирование и т. Д. Если вы оставите это как динамическое поле, ваш индекс также придется перестраивать на лету, если он у вас есть.

Стандартная процедура заключается в перемещении этого кода и вычислении & обновления поля ComputedValue на лету, когда вы обновляете любой из двух других. И если в вашем коде есть более одного места, где вы обновляете это поле, я бы посмотрел на оптимизацию вашего кода.

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