SQL - Оптимизация производительности массовых вставок и больших объединений? - PullRequest
3 голосов
/ 05 августа 2009

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

Чтобы поставить вопрос в контексте, вот обзор того, что я делаю в настоящее время:

  1. Бросьте все внешние ключи и уникальные ограничения
  2. Импорт данных (~ 100 миллионов записей)
  3. Повторно создайте ограничения и выполните анализ таблицы фактов.

Импорт данных осуществляется путем загрузки из файлов. Для каждого файла:

1) Загрузка данных из временной таблицы с помощью COPY (инструмент массовой загрузки PostgreSQL)

2) Обновите каждую из 9 таблиц измерений новыми данными, используя вставку для каждой, например:

INSERT INTO host (name)
SELECT DISTINCT host_name FROM temp_table
EXCEPT
SELECT name FROM host;
ANALYZE host;

Анализ выполняется в конце INSERT с целью поддержания статистики в актуальном состоянии в течение десятков миллионов обновлений (это целесообразно или необходимо? Как минимум, это, по-видимому, существенно не снижает производительность) .

3) Затем таблица фактов обновляется нечестивым 9-сторонним объединением:

INSERT INTO event (time, status, fk_host, fk_etype, ... ) 
SELECT t.time, t.status, host.id, etype.id ... 
FROM temp_table as t 
JOIN host ON t.host_name = host.name
JOIN url ON t.etype = etype.name
... and 7 more joins, one for each dimension table

Есть ли лучшие подходы, которые я пропускаю?

Ответы [ 2 ]

1 голос
/ 06 августа 2009

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

0 голосов
/ 05 августа 2009

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

Вместо этого я бы рекомендовал создать одного sproc для вставки в вашу таблицу фактов; например insertXXXFact(...), который вызывает ряд других sprocs (по одному на измерение) в соответствии с соглашением об именах getOrInsertXXXDim, где XXX - это рассматриваемое измерение. Каждый из этих sprocs будет либо искать, либо вставлять новую строку для данного измерения (таким образом обеспечивая ссылочную целостность) и должен возвращать первичный ключ измерения, на который должна ссылаться таблица фактов. Это значительно сократит объем работы, которую необходимо выполнить на этапе 3, который теперь сводится к вызову вида insert into XXXFact values (DimPKey1, DimPKey2, ... etc.)

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

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