Как мне вести точные записи, суммирующие несколько таблиц? - PullRequest
1 голос
/ 04 июня 2009

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

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

Я подошел к аналогичной проблеме, когда мне потребовалась сводка по одной таблице, организовав итерацию по каждой строке в таблице и отслеживая состояние итератора и наивысшую начальную остроту (то есть "highwater"), которую видели. Это хорошо для одной таблицы, но для нескольких таблиц я бы в итоге оставил одно значение highwater на таблицу, и это кажется сложным. В качестве альтернативы я мог бы денормализовать до одной таблицы (с довольно обширными изменениями приложения), которая чувствует шаг назад и, вероятно, изменила бы размер моей базы данных с примерно 5 ГБ до примерно 20 ГБ.

(на данный момент я использую sqlite3, но MySQL также является опцией).

Ответы [ 5 ]

2 голосов
/ 04 июня 2009

Я вижу два подхода:

  1. Вы перемещаете данные в отдельную базу данных, денормализованы, производите некоторый предварительный расчет, чтобы оптимизировать их для быстрого доступа и создания отчетов (звучит как небольшое хранилище данных). Это подразумевает, что вам нужно подумать о некоторых заданиях (сценарии, отдельное приложение и т. Д.), Которые копируют и преобразуют данные из источника в место назначения. В зависимости от того, как вы хотите, чтобы было выполнено копирование (полное / инкрементное), частоты копирования и сложности модели данных (как исходной, так и целевой), может потребоваться некоторое время для реализации, а затем для оптимизации процесса. Он имеет то преимущество, что оставляет исходную базу данных нетронутой.

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

1 голос
/ 04 июня 2009

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

Если это инкрементное обновление, то вам нужно, чтобы диапазоны PK работали в любом случае, поэтому вы захотите что-то вроде ваших данных верхней отметки (за исключением того, что вы можете хранить минимальные / максимальные пары).

1 голос
/ 04 июня 2009

Вы можете создавать триггеры.

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

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

Пример:

CREATE TRIGGER update_summary_table UPDATE OF order_value ON orders 
BEGIN
  UPDATE summary 
    SET total_order_value = total_order_value 
                          - old.order_value 
                          + new.order_value 
    // OR: Do a complete recalculation
    // OR: Store a flag
END;

Дополнительная информация о триггерах SQLite: http://www.sqlite.org/lang_createtrigger.html

0 голосов
/ 08 июня 2009

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

Тогда я думаю, что обсуждаемый вариант триггера также является очень хорошей стратегией.

Другой возможностью является регулярное заполнение хранилища данных моделью, подходящей для высокопроизводительных отчетов (например, модель Кимбалла).

0 голосов
/ 08 июня 2009

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

...