Агрегаты на больших базах данных: лучшая платформа? - PullRequest
3 голосов
/ 27 октября 2010

У меня есть база данных postgres с несколькими миллионами строк, которая управляет веб-приложением. Данные статичны: пользователи не пишут в них.

Я хотел бы иметь возможность предлагать пользователям агрегаты с возможностью запроса (например, сумму всех строк с определенным значением внешнего ключа), но размер базы данных теперь означает, что для расчета таких агрегатов требуется 10-15 минут.

Должен ли я:

  1. начать предварительный расчет агрегатов в базе данных (поскольку данные статичны)
  2. отойти от postgres и использовать что-то еще?

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

Если бы для таких проблем было лучшее решение, чем postgres, я был бы очень благодарен за любые предложения.

Ответы [ 7 ]

3 голосов
/ 31 октября 2010

Вы пытаетесь решить проблему со структурой базы данных OLAP (On-Line Analytical Process) со структурой базы данных OLTP (On-Line Transactional Process).

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

Единственное предостережение в том, что агрегированные данные всегда будут отставать на один день.

1 голос
/ 27 октября 2010
  1. Да
  2. Возможно.Предположительно, есть целая куча вещей, которые вы должны рассмотреть, прежде чем менять свою RDBMS.Если вы перешли на SQL Server, для этого вам понадобятся индексированные представления: Повышение производительности с помощью индексированных представлений SQL Server 2008
0 голосов
/ 28 октября 2010

Oracle поддерживает концепцию под названием Query Rewrite.Идея такова:

Когда вы хотите, чтобы поиск (WHERE ID = val) шел быстрее, вы добавляете индекс.Вам не нужно указывать оптимизатору использовать индекс - он просто делает.Вам не нужно изменять запрос для чтения из индекса ... вы попадаете в ту же таблицу, что и всегда, но теперь вместо чтения каждого блока в таблице он читает несколько блоков индекса и знает, куда идти вТаблица.

Представьте себе, если бы вы могли добавить что-то подобное для агрегации.Что-то, что оптимизатор просто «использовал бы» без подсказки изменить.Допустим, у вас есть таблица DAILY_SALES за последние десять лет.Некоторые менеджеры по продажам хотят ежемесячные продажи, некоторые - ежеквартально, некоторые - ежегодно.

Вы можете сохранить кучу дополнительных таблиц, содержащих эти агрегации, а затем попросить пользователей изменить свой запрос на использование другой таблицы.,В Oracle вы бы построили их как материализованные представления.Вы не работаете, кроме определения MV и MV Log в исходной таблице.Затем, если пользователь запрашивает у DAILY_SALES сумму за месяц, ORACLE изменит ваш запрос на использование соответствующего уровня агрегации.Ключ БЕЗ изменения запроса вообще.

Может быть, поддержка других БД, что ... но это, безусловно, то, что вы ищете.

0 голосов
/ 27 октября 2010

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

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

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

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

0 голосов
/ 27 октября 2010

Для этого объема данных вам не нужно выходить из Postgres.

Сначала я посмотрю на настройку - 10-15 минут кажутся чрезмерными для «нескольких миллионов строк». Это должно быть всего несколько секунд. Обратите внимание, что стандартные настройки конфигурации для Postgres не выделяют (или, по крайней мере, не выделяют) большой объем дискового буфера. Вы можете посмотреть на это тоже.

Более сложные решения включают в себя реализацию некоторого вида витрины данных или внешнего интерфейса OLAP, такого как Mondrian, по базе данных. Последний предварительно рассчитывает агрегаты и кэширует их.

0 голосов
/ 27 октября 2010

Если вы храните агрегаты в промежуточном объекте (что-то вроде MyAggragatedResult), вы можете рассмотреть кеширующий прокси:

класс ResultsProxy { convertResult (param1, param2) { .. извлечь из кеша .. если не найден, рассчитать и сохранить в кеше }

}

Существует довольно много рамок кэширования для java, и больше всего подходит для других языков / сред, таких как .Net. Это решение может позаботиться о недействительности (как долго должен храниться результат в памяти) и управлении памятью (удаляет старые элементы кэша при достижении предела памяти и т. Д.).

0 голосов
/ 27 октября 2010

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

Пример: скажем, вы пишете систему учета. Все дебеты и кредиты хранятся в таблице Главной книги (GL). Такая таблица может быстро накапливать десятки миллионов строк в занятой организации. Чтобы найти остаток на конкретном счете в балансе по состоянию на данный день, обычно необходимо рассчитать сумму всех дебетов и кредитов на этом счете до этой даты, расчет, который может занять несколько секунд даже при правильном индексированная таблица. Расчет всех показателей баланса может занять несколько минут.

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

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