Реклама
Комментарии 24
А в чём преимущества описанного подхода по сравнению с использованием отдельных ETL-инструментов? Ну, например, Apache NiFi.
Например, одно из преимуществ в том, что вы полностью контролируете все операции на каждом этапе (и понимаете как и когда они происходят). То есть когда такой импорт — лишь одна, и не доминирующая, функция вашего продукта.

Например, тот же импорт выписки из клиент-банка и связывание платежек со счетами для интернет-магазина. Разворачивать ради одной такой функции дополнительный не особо простой софт не всегда эффективно по сравнению с «сделал сам в 5 строк».
С другой стороны, тот же NiFi:

1) в аббревиатуре ETL выполнит букву E (Вы привели пример с КЛАДР (ныне ФИАС), я сейчас работаю ЕГРЮЛ — в любом случае, это загрузка с внешнего HTTP/FTP с учётом ранее загруженного);

2) проверит соответствие загруженных данных схеме, сообщит в случае ошибки (мало ли что поменяют или выложат битый файл, бывало);

3) выполнит букву T, не грузя этим сервер БД, которому и так есть чем заняться (в случае с ЕГРЮЛ — разделит скачанный XML на отдельные события по каждому юр. лицу, в КЛАДР/ФИАС тоже надо осуществить что-то подобное, наверняка);

4) размажет по времени букву L, чтобы и тут не создавать пиковых нагрузок на БД;

5) уведомит другие сервисы, которым надо бы узнать о произошедшем, не запрашивая постоянно БД (в моём случае — опубликует сообщение в Kafka).

Ваше решение обеспечивает только четвёртый пункт. Ну и по степени контроля над процессом / подробности логирования тоже к NiFi и аналогам придраться сложно. Я как раз думал, что именно эту часть процесса подобный софт и облегчает.
Я не говорю, что другие инструменты не нужны, но дополнительно к СУБД и БЛ, которая и делает парсинг XML в адекватной схеме (а явно не БД), вы уже ввели в систему NiFi и Kafka. Не каждый разработчик готов сразу шагать в «суровый энтерпрайз», кому-то предложенного подхода может оказаться вполне достаточно.
Просто я уже влез вот в эти все фишки из «сурового энтерпрайза» в своём стартапном по сути проекте — и пытаюсь найти этому оправдание :)
Не стоит тут искать оправдание. Инструменты, работающие вне СУБД, для таких задач намного удобнее (я правда назвал бы Camel, но не думаю что это принципиально).

И как-то знаете,
>когда объем этого «чего-то» начинает измеряться сотнями мегабайт
у меня вызывает вопросы: а почему не гигабайт? Как-то маловато будет. Сотни мегабайт — это на сегодня намного меньше типового объема оперативки. Т.е. работаем по сценарию «залили все в память, там переварили, вернули в БД». И никаких проблем при этом. Более того, я по такому сценарию еще в 2010 примерно работал — и мы получили ускорение (не на ETL правда, а на отчете) на пару порядков.
Терабайт уже хорошие размерчики, у нас есть некоторое число таких табличек, и могу честно сказать, что почти каждая из них требует какого-либо индивидуального подхода, чтобы не работать сутками, а уложиться например часа в четыре.

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

Пишите, почитаем)
почти каждая из них требует какого-либо индивидуального подхода, чтобы не работать сутками, а уложиться например часа в четыре
Нет, у нас это не время обработки, а просто входящий объем — 1TB/сутки. Обработка делается параллельно.
Ну т.е. можно ли реально написать хранимку, которая употребит имеющиеся на машинке условные полтерабайта оперативки?
Написать можно, но обычно это плохо заканчивается приходом OOM Killer, потому что является результатом какой-то плохо ограниченной рекурсии. В реальных применениях гораздо чаще произойдет использование temp buffers.
>Нет, это не время обработки, а входящий объем.
Обычно есть ограничения и на время обработки (скажем, входящие за вчера нужно обработать сегодня, а лучше до утра, а иначе отчеты за вчера будут только послезавтра). А уж параллелить и так есть что — если у нас в наличии таблица скажем пять терабайт, это не значит, что она в схеме одна — там может быть их еще пятьсот.

Так что у нас вся обработка и так параллелится, это вообще Хадуп в моем случае. Штук 400 процессов вполне типично для нескольких терабайт одной таблицы. А для тех где до 10 терабайт в сутки только изменений — там вообще история совсем отдельная.
Обычно есть ограничения и на время обработки (скажем, входящие за вчера нужно обработать сегодня, а лучше до утра, а иначе отчеты за вчера будут только послезавтра).
У нас чуток другая специфика — отчеты нужны с отставанием не больше минуты, практически онлайн.
Штук 400 процессов вполне типично для нескольких терабайт одной таблицы. А для тех где до 10 терабайт в сутки только изменений — там вообще история совсем отдельная.
Было бы интересно почитать.
Ну, терабайт в отлайне не получается никак. Тупо в диски упирается, например. А в целом стратегия работы с терабайтами в хадупе — это довольно интересная тема, только очень техническая, я не уверен, что готов по ней что-то интересное написать. С одной стороны, все в общем просто — берем терабайт, берем скажем 100 узлов кластера, уже получилось 10 гигабайт на узел — не так и много. То есть, если мы обработку можем тупо распараллелить на 100 потоков (так, чтобы потом не забить всю сеть обменом промежуточными результатами) — мы все сделаем с такой скоростью, как будто это были 10 гигабайт. Ну, почти.

А дальше уже идут попытки найти алгоритм, который хорошо параллелится. Скажем, сортировка параллелится не очень, а фильтр Блума — сильно лучше.
Ну, терабайт в отлайне не получается никак. Тупо в диски упирается, например.
При работе «на потоке», если БД используется не для извлечения сырых данных, а для их записи и результатов обработки, цифры выглядят уже не столь пугающе: 1TB/сутки = avg 12.7MB/s.

С учетом колебаний нагрузки день-ночь реальные пики получаются больше, но не выше 100MB/s обычно, SSD спокойно справляются. Но это как раз история про «индивидуальный подход» к данным, да.
>вы уже ввели в систему NiFi и Kafka
Собственно, а попробуйте каким-то образом сообщить другим процессам, если у вас таковые есть, что в БД что-то произошло? У вас так или иначе появится какой-то messaging, не кафка, так JMS, не ActiveMQ, так QPID. Наличие messaging — это не недостаток, скажем прямо. Это особенность развитой архитектуры (во завернул :)

А вот у решения «целиком внутри БД» есть один существенный недостаток — оно делается как правило на одном языке, который не очень хорошо подходит для каких-либо задач помимо манипулирования собственно данными из базы.

Это и для PL/SQL в общем так, и для постгреса, да и для MS SQL не сильно отличается. Даже там, где можно применить скажем Java (в Oracle), или C# (MS SQL), это выливается в совершенно ненужные приседания, и обычно проще все сделать снаружи БД, нежели внутри.

>Не каждый разработчик готов сразу шагать
Ну да, если такое ограничение для вас имеет место — тогда решение как решение, почему нет?
Собственно, а попробуйте каким-то образом сообщить другим процессам, если у вас таковые есть, что в БД что-то произошло? У вас так или иначе появится какой-то messaging, не кафка, так JMS, не ActiveMQ, так QPID. Наличие messaging — это не недостаток, скажем прямо.
В некоторых случаях и для этого «не выходя из БД» можно messaging использовать.
Ну это вы про сообщения внутри, да. Такое и у MS SQL есть. И такое иногда очень полезно — потому что послав сообщение, вы автоматически его обработку сделаете в другой транзакции. Вот только с другими системами такое не очень удобно стыкуется. Послать-то можно — вызов хранимой процедуры, и ок, а вот получить без опроса как-то не очень выходит, надо чтобы хранимая процедура хотя бы REST научилась вызывать, например.
А нужно? по моему опыту это такое безобразие, что лучше от него подальше держаться.
Как минимум у Talend и Pentaho есть батч-ETL инструменты (+community-версии). Работают со всем, где есть JDBC-драйвер.
ALTER TABLE… RENAME… / DROP TABLE…

ломаются все внешние ключи (FK) на таблицу


Можете привести подтверждение? Не нашел подобной информации в сети.

UPD:
Просто нельзя сделать DROP таблицы не каскадно если есть хоть один FK на нее. Думал что то другое.

Спасибо за статью
К примеру выше:
CREATE TABLE client_tmp(
  LIKE client INCLUDING ALL
);

DROP TABLE client;
-- ERROR:  cannot drop table client because other objects depend on it
-- DETAIL:  constraint invoice_client_id_fkey on table invoice depends on table client
-- HINT:  Use DROP ... CASCADE to drop the dependent objects too.

DROP TABLE client CASCADE;
-- NOTICE:  drop cascades to constraint invoice_client_id_fkey on table invoice

ALTER TABLE client_tmp RENAME TO client;
-- табличка вообще тут сейчас пустая

INSERT INTO invoice(client_id) VALUES(1);
-- все вставилось - oops!

А потому что CASCADE снесло invoice_client_id_fkey, и его надо накатывать заново.
Только полноправные пользователи могут оставлять комментарии. , пожалуйста.