November 2019

S M T W T F S
      12
34 5 678 9
10111213141516
17181920212223
24252627282930

Style Credit

Expand Cut Tags

No cut tags
Saturday, August 16th, 2014 12:17 pm

В одной базе данных есть две таблицы, связанные отношением 1:M. Скажем, в одной лежат посты из блога, а в другой комментарии, привязанные к постам по id.
Задача: перетащить их все в другую базу, в которой идентификаторы у постов изменятся (потому что там уже есть другие посты с теми же id, что в первой базе), но при этом сохранить привязку к ним комментариев.

С постами понятно, SELECT из первой базы и INSERT во вторую.

А вот как быть с комментариями?
Мне пока пришли в голову три идеи, но все неэффективные.

1) Для каждого поста сразу после помещения его во вторую базу, когда уже известны и старый, и новый id, найти в первой базе все комментарии по старому id и сложить их во вторую базу с новым id. Но это отдельный SQL-запрос на каждый пост, а их там дофига.

2) Сначала перенести все посты, попутно составляя табличку со старыми и новыми id, а потом переносить комментарии, заменяя id постов по этой табличке. Но если табличку держать в памяти, она получится очень нефигового размера. А в базах её создавать нельзя, правов не хватает.

3) Извлечь вместе с постами сразу все их комментарии путём LEFT OUTER JOIN. Но тогда каждый пост извлечётся целиком много раз, с каждым своим комментарием, это дикий перерасход памяти в SQL-сервере.

Как бы это сделать поэффективнее?

Оригинал этой записи в личном блоге.

Saturday, August 16th, 2014 03:46 pm (UTC)
Первый вариант. Запусти скрипт с вечера, пусть жужжит. Твое время всяко дороже машинного :)
Saturday, August 16th, 2014 03:47 pm (UTC)
Так завести отдельное unique поле, в которое писать origin ID?
Saturday, August 16th, 2014 07:44 pm (UTC)
temporary table тоже не дадут создать?
Tuesday, August 19th, 2014 09:47 pm (UTC)
Синтаксис оператора CREATE TABLE

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)]
[table_options] [select_statement]

Но нужны соответствующие права.
Saturday, August 16th, 2014 05:46 pm (UTC)
а) Заюзать какой-нибудь ORM системы DBIx::Class, который вытащит посты с комментами. Из базы взял - в базу положил...

б) Импортировать посты, взять новые ID, сохранить в старой базе, взять из старой базы комменты с новыми ID постов, залить.

А почему ID сохранить не удается, кстати?
Saturday, August 16th, 2014 06:08 pm (UTC)
Ну вот есть там магия, которая из результатов запроса с LEFT JOIN делает структуру 1:N. В потроха не лез, мне хватает, что просто работает.

Простейший способ эмуляции совсем на коленке - вытащить LEFT JOIN-ом, и следить, какой пост импортируем.
Sunday, August 17th, 2014 06:58 am (UTC)
Взять максимальный ID поста таргетной таблицы и добавлять его к значениям сорсевых таблиц при переносе? Нумерация постов обычно от единицы и более-менее непрерывная, т.ч. результат должен выйти близкий.
Sunday, August 17th, 2014 07:00 am (UTC)
Но, конечно, сработает только если можно обеспечить отсутствие инсертов на таргетной таблице в процессе переноса.
Sunday, August 17th, 2014 05:16 pm (UTC)
LOCK TABLE?