2009-08-05 3 views
3

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

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

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

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

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

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

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

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

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 

Существуют ли более эффективные подходы, я с видом?

ответ

1

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

0

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

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

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

+1

Я согласен в принципе, но когда я пробовал этот подход, я обнаружил, что он в среднем на 50% медленнее. Это похоже на кэширование таблиц измерений в сочетании с выполнением всего, поскольку массовые операции (а не отдельные выборки/вставки) выполняются быстрее. – Rob

+1

@ Rob: Это интересно, поскольку это подход, который работал для меня в прошлом. Кстати, я не могу поверить, что этот ответ был ниспослан без каких-либо комментариев! – Adamski

Смежные вопросы