Перемещение данных из таблицы в другую в postgresql - PullRequest
0 голосов
/ 16 октября 2018

У меня есть 2 таблицы в моей базе данных.У них более 16 млн записей, у них одинаковый uuid для отношения (у меня есть индексы для обоих полей uuid).Один из них похож на 166 ГБ, а другой - на 50 ГБ.Я поменяю имена таблиц на мой вопрос, но я надеюсь, что вы получите вопрос.

Допустим, моя первая таблица называется users, а вторая - profile.Теперь у меня есть поле в таблице пользователей, и я хочу скопировать его в таблицу профилей.

Я что-то сделал вчера вечером, но он все еще обрабатывается и уже более 10 часов.

У меня сейчас 3 вопроса.Первый вопрос;мои вопросы в порядке?

ALTER TABLE profiles ADD COLUMN start_stamp TIMESTAMP DEFAULT NOW();
SET start_stamp = (SELECT start_stamp::DATE FROM users WHERE uuid = profiles.uuid);
CREATE INDEX start_stamp ON profiles;

И второй вопрос;есть ли разница между этими двумя запросами?Если да, в чем разница и какая из них лучше?

UPDATE profiles 
SET start_stamp = (SELECT start_stamp::DATE FROM users WHERE uuid = profiles.uuid);

QUERY PLAN
--------------------------------------------------------------------------
Update on profiles  (cost=0.00..159956638.61 rows=18491638 width=116)
->  Seq Scan on profiles  (cost=0.00..159956638.61 rows=18491638 width=116)
     SubPlan 1
       ->  Index Scan using unique_user_uuid on users  (cost=0.56..8.58 rows=1 width=20)
             Index Cond: ((uuid)::text = (profiles.uuid)::text)




UPDATE profile
SET start_stamp = users.start_stamp
FROM users
WHERE profiles.start_stamp = users.start_stamp;

QUERY PLAN
--------------------------------------------------------------------------
Update on profiles  (cost=2766854.25..5282948.42 rows=11913522 width=142)
->  Hash Join  (cost=2766854.25..5282948.42 rows=11913522 width=142)
     Hash Cond: ((profiles.uuid)::text = (users.uuid)::text)
     ->  Seq Scan on profiles  (cost=0.00..1205927.56 rows=18491656 width=116)
     ->  Hash  (cost=2489957.22..2489957.22 rows=11913522 width=63)
           ->  Seq Scan on users  (cost=0.00..2489957.22 rows=11913522 width=63)

И мой последний вопрос:Есть ли лучший способ скопировать значение из таблицы в другую с более чем 16 м и 200 ГБ записей?

Спасибо.

Ответы [ 2 ]

0 голосов
/ 18 октября 2018

Оба ваших запроса одинаковы. Обновление займет вечность. Это хорошо известная проблема, добавляющая NOT NULL COLUMN в большую таблицу

Sol1: обновление значений по умолчанию в чанках, выполнение нескольких запросов для обновлениядата Sol2: воссоздать всю таблицу

Полезные ссылки для большого количества строк в Postgres: https://medium.com/doctolib-engineering/adding-a-not-null-constraint-on-pg-faster-with-minimal-locking-38b2c00c4d1c

https://dba.stackexchange.com/questions/52517/best-way-to-populate-a-new-column-in-a-large-table/52531#52531

https://dba.stackexchange.com/questions/41059/optimizing-bulk-update-performance-in-postgresql

0 голосов
/ 18 октября 2018

Самый быстрый способ обновить / скопировать огромное количество данных - это CTAS (создать таблицу как выбранную).Это возможно, только если у вас есть права на это, и вы можете изменить имена или удалить исходную таблицу.

В вашем случае это будет выглядеть так:

create table tmp_profiles as
select p.* , us.strat_stamp:date
 from profiles p
 left join users u on p.uuid = us.uuid;

drop table profiles;

alter table tmp_profiles, rename to profiles;

После этого вам придетсявоссоздайте свои ключи, индексы и другие ограничения.

Если вы обновите более 5% записей в вашей таблице, CTAS будет как минимум в несколько раз быстрее, чем обычное обновление.Ниже этого порога обновление может быть быстрее, чем CTAS.

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