LINUX.ORG.RU

О-о-очень большой JOIN

 ,


0

3

Добрый день!

У меня есть примерно следующие вещи:

  • БД: Postgres или Greenplum
  • madlib: библиотека для различной статистики и мэшин-лернинга

А теперь происходит следующее: я строю очень много деревьев принятия решений (штук 20-50), по каждому из них делаю предсказание. Получаю 50 табличек, состоящих из одинакового числа строчек (может быть дофига, до нескольких миллионов) и двух столбиков: primary key (везде одинаковые) и вещественный value.

Так вот, так как дальше мне надо строить логистическую регрессию, все эти таблички надо объединить в одну большую. Я придумал два способа: либо CREATE TABLE blablabla as SELECT ... и JOIN по всем этим дофига таблицам, либо создаем пустую таблицу, и потом UPDATE'ом туда пихаем данные (что уже хуже первого решения).

Проблема вся в том, что в Постгресе джойн работает хорошо, но на больших объемах ему не хватает оперативки (несколько гигов), и он падает. В Greenplum же запрос с JOIN на любом числе строчек (даже сотне) вешает ядро намертво, UPDATE же работает за квадратичную (!) асимптотику.

Вопрос: что же делать? Может есть какие-то советы?

Ответ на: комментарий от AnDoR

Использовать что угодно иное, более подходящее (Spark?) — вариант. В т.ч. и запихнуть все в память.

Только вот до моего начальника не доходит.

FuriousBean
() автор топика
Ответ на: комментарий от anonymous

Так union конкатенирует строчки, а мне надо столбцы.

FuriousBean
() автор топика

UPDATE же работает за квадратичную (!) асимптотику

Если я правильно понял проблему…
Эту таблицу создаёшь с индексами? А если сначала влить в таблицу всю инфу, а уже потом создать индексы? Когда вставляешь или обновляешь строку в таблицу то пересчитываются все затронутые индексы, если вставлять 100 строк (во всяком случае если по запросу на строку) то индекс будет пересчитан 100 раз. С миллионами строк это становится грустно. Поэтому при массовом INSERT/UPDATE бывает смысле отключать индексы и потом создавать их заново.

MrClon ★★★★★
()
Ответ на: комментарий от MrClon

Да, индексы и их обновление могли бы объяснить многие вещи. Но нет, я их не создаю.

FuriousBean
() автор топика

Если кому интересно: Greenplum выдает вот такой вот Execution Plan. То есть оно по одной строчке за раз вытаскивает, что уже слоупочно. Но самое смешное в том, что этот подзапрос выполняется не за константу (мерил при различном числе строк), а за линию или типа того. Это объясняет квадрат.

На эксплэйне большого джойне Greenplum и вовсе повисает.


Update (slice0; segments: 4)  (rows=1434 width=18)
  ->  Explicit Redistribute Motion 4:4  (slice21; segments: 4)  (cost=0.00..4209681.44 rows=1434 width=18)
        ->  Seq Scan on test__training__scoretable  (cost=0.00..4209681.44 rows=1434 width=18)
              SubPlan 20
                ->  Result  (cost=36.71..36.72 rows=1 width=8)
                      Filter: test__training_dum19.id = $0
                      ->  Materialize  (cost=36.71..36.72 rows=1 width=8)
                            ->  Broadcast Motion 4:4  (slice20; segments: 4)  (cost=0.00..36.71 rows=1 width=8)
                                  ->  Seq Scan on test__training_dum19  (cost=0.00..36.71 rows=1 width=8)
...
...
...
              SubPlan 1
                ->  Result  (cost=36.71..36.72 rows=1 width=8)
                      Filter: test__training_dum0.id = $0
                      ->  Materialize  (cost=36.71..36.72 rows=1 width=8)
                            ->  Broadcast Motion 4:4  (slice1; segments: 4)  (cost=0.00..36.71 rows=1 width=8)
                                  ->  Seq Scan on test__training_dum0  (cost=0.00..36.71 rows=1 width=8)


FuriousBean
() автор топика
Ответ на: комментарий от FuriousBean

greenplum это база с колоночным хранением, она не предназначена для абдейтов. покажи explain analyze select'а из CTAS work_mem какой?

drsm ★★
()

Денормализуй в одну траблицу все и храни в какой-нибудь молодежной кассандре или просто в одной таблице в постгресе.

anonymous
()

JOIN по всем этим дофига таблицам

Можно разбить процесс на INSERT INTO TEMP t1 SELECT ... FROM a1 join a2 on ...; INSERT INTO TEMP t2 SELECT ... FROM t1 join a3 on ...; ...

Ну и временные таблицы дропать как только они дальше не нужны. Должно помочь с памятью.

monk ★★★★★
()

В общем, забейте.

Я отказался от объединения пятидесяти таблиц в пользу создания сразу нужной таблицы, т.к. функция предсказания по дереву классификации выражается простым набором if-иков (ну или CASE WHEN ... в случае SQL), и, избавившись от джойнов и апдейтов, получил космический выигрыш по времени и памяти.

Всем спасибо :)

FuriousBean
() автор топика
Ответ на: комментарий от drsm

Да, greenplum поддерживает колоночное хранение. Здорово. Но каким запросом заставить объединить эти дохрена колонок я так и не понял. JOIN как по пятидесяти, так и по двадцати таблицам вешает оптимайзер запросов намертво, а update это заведомо ущербное решение.

В теории при колоночном хранении объединение столбцов — это очень дешевая операция, а на деле Pivotal'ская документация крайне убогая, и я не нашел сходу таких примеров.

FuriousBean
() автор топика
Ответ на: комментарий от monk

Получаем квадратичную асимптотику по количеству столбцов, что уже крайне плохо.

FuriousBean
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.