Регистрация  |  Вход

Перелинковка связей на объекте и его записях

Еще раз всем привет!

столкнулся с рабочей задачей по оптимизации схемы базы данных в рабочем Орге.

Тема, думаю, вам понравится.

В системе есть кастомный объект много лет выполнявший роль этакого кастомного "Аккаунта". И все вновь создаваемые каст объекты имеют лук-ап на него.

Теперь выясняется что в стандартном Аккаунт иерархию записей организовать много проще.

И необходимо все записи из кастомного Аккаунт "скопировать" в станд Аккаунт. На другие кастом объекты добавить новый лук-ап на станд Аккаунт. И самое главное - сделать "перелинковку". То есть написать скрипт, который в каждой записи какого-то кастомного объекта прописывает в новый лук-ап на станд Аккаунт ту запись, которая соответсвует (по какому-то признаку) записи указанной в лук-апе данной записи на кастомный Аккаунт. Логика понятна.

Не понятно как это все физически организовать в Проде:

(1) где выполнять скрипт? в Эклипсе? девелопер консоль?

(2) как бороться с лимитами, если к примеру нужно перебрать все 10 тысяч записей в кастомном объекте?

а может это можно сделать в Workbench?

любые ваши идеи - very welcome.

тема не простая, но в практике наверняка придется каждому сталкиваться с такой оптимизацией "живой" БД с соответсвующей перелинковкой связанных записей.

спасибо

Еще раз всем привет!

столкнулся с рабочей задачей по оптимизации схемы базы данных в рабочем Орге.
Тема, думаю, вам понравится.

В системе есть кастомный объект много лет выполнявший роль этакого кастомного "Аккаунта". И все вновь создаваемые каст объекты имеют лук-ап на него.
Теперь выясняется что в стандартном Аккаунт иерархию записей организовать много проще.
И необходимо все записи из кастомного Аккаунт "скопировать" в станд Аккаунт. На другие кастом объекты добавить новый лук-ап на станд Аккаунт. И самое главное - сделать "перелинковку". То есть написать скрипт, который в каждой записи какого-то кастомного объекта прописывает в новый лук-ап на станд Аккаунт ту запись, которая соответсвует (по какому-то признаку) записи указанной в лук-апе данной записи на кастомный Аккаунт. Логика понятна.

Не понятно как это все физически организовать в Проде:
(1) где выполнять скрипт? в Эклипсе? девелопер консоль? 

(2) как бороться с лимитами, если к примеру нужно перебрать все 10 тысяч записей в кастомном объекте?

а может это можно сделать в Workbench?

любые ваши идеи - very welcome.

тема не простая, но в практике наверняка придется каждому сталкиваться с такой оптимизацией "живой" БД с соответсвующей перелинковкой связанных записей.

спасибо

Den Brown
Еще раз всем привет!

столкнулся с рабочей задачей по оптимизации схемы базы данных в рабочем Орге.
Тема, думаю, вам понравится.

В системе есть кастомный объект много лет выполнявший роль этакого кастомного "Аккаунта". И все вновь создаваемые каст объекты имеют лук-ап на него.
Теперь выясняется что в стандартном Аккаунт иерархию записей организовать много проще.
И необходимо все записи из кастомного Аккаунт "скопировать" в станд Аккаунт. На другие кастом объекты добавить новый лук-ап на станд Аккаунт. И самое главное - сделать "перелинковку". То есть написать скрипт, который в каждой записи какого-то кастомного объекта прописывает в новый лук-ап на станд Аккаунт ту запись, которая соответсвует (по какому-то признаку) записи указанной в лук-апе данной записи на кастомный Аккаунт. Логика понятна.

Не понятно как это все физически организовать в Проде:
(1) где выполнять скрипт? в Эклипсе? девелопер консоль?

(2) как бороться с лимитами, если к примеру нужно перебрать все 10 тысяч записей в кастомном объекте?

а может это можно сделать в Workbench?

любые ваши идеи - very welcome.

тема не простая, но в практике наверняка придется каждому сталкиваться с такой оптимизацией "живой" БД с соответсвующей перелинковкой связанных записей.

спасибо

Ух.. ну расказываю как это делал я.

1. Делаем сандбокс (дев) в общем что позволяет заказчик. Лучше всего full sandbox.
2. Делаем копию с прода на этот сендбокс. Далее буду описывать процесс касательно full sandbox
3. Выкачиваем в эклипс или в другую среду всю метадату.
4. Делаем замену одного объекта на другой во всей метадате через REGEX
5. Заливаем все что поменяли на сандбокс. Если есть проблем решаем ручками.
6. Копируем данные из одного объекта в другой. Пишем скрипт для замены одного ID на другой во всей базе.
7. Когда закончили с сендбоксом. переходим к проду. Делаем бакап прода и метаданных и данных.
8. Выбираем время когда нагрузка на прод минимальна, обычно это ночь.
9. Заливаем новую метадату на прод. Проверяем что все залилось правильно.
10. Делаем все тое самое что делали с сандбоксом.

При нормальном раскладе занимаем часа 2-3 на проде. весь процесс обычно занимает 2-5 дней. Зависит от объема и сложности.

[quote="Den Brown"]Еще раз всем привет!

столкнулся с рабочей задачей по оптимизации схемы базы данных в рабочем Орге.
Тема, думаю, вам понравится.

В системе есть кастомный объект много лет выполнявший роль этакого кастомного "Аккаунта". И все вновь создаваемые каст объекты имеют лук-ап на него.
Теперь выясняется что в стандартном Аккаунт иерархию записей организовать много проще.
И необходимо все записи из кастомного Аккаунт "скопировать" в станд Аккаунт. На другие кастом объекты добавить новый лук-ап на станд Аккаунт. И самое главное - сделать "перелинковку". То есть написать скрипт, который в каждой записи какого-то кастомного объекта прописывает в новый лук-ап на станд Аккаунт ту запись, которая соответсвует (по какому-то признаку) записи указанной в лук-апе данной записи на кастомный Аккаунт. Логика понятна.

Не понятно как это все физически организовать в Проде:
(1) где выполнять скрипт? в Эклипсе? девелопер консоль? 

(2) как бороться с лимитами, если к примеру нужно перебрать все 10 тысяч записей в кастомном объекте?

а может это можно сделать в Workbench?

любые ваши идеи - very welcome.

тема не простая, но в практике наверняка придется каждому сталкиваться с такой оптимизацией "живой" БД с соответсвующей перелинковкой связанных записей.

спасибо[/quote]

Ух.. ну расказываю как это делал я.

1. Делаем сандбокс (дев) в общем что позволяет заказчик. Лучше всего full sandbox.
2. Делаем копию с прода на этот сендбокс. Далее буду описывать процесс касательно full sandbox
3. Выкачиваем в эклипс или в другую среду всю метадату.
4. Делаем замену одного объекта на другой во всей метадате через REGEX
5. Заливаем все что поменяли на сандбокс. Если есть проблем решаем ручками.
6. Копируем данные из одного объекта в другой. Пишем скрипт для замены одного ID на другой во всей базе.
7. Когда закончили с сендбоксом. переходим к проду. Делаем бакап прода и метаданных и данных.
8. Выбираем время когда нагрузка на прод минимальна, обычно это ночь.
9. Заливаем новую метадату на прод. Проверяем что все залилось правильно.
10. Делаем все тое самое что делали с сандбоксом. 

При нормальном раскладе занимаем часа 2-3 на проде. весь процесс обычно занимает 2-5 дней. Зависит от объема и сложности.

Млин, сложный процесс. Wilder, и часто тебе приходилось этим заниматься?

Млин, сложный процесс. Wilder, и часто тебе приходилось этим заниматься?

wilder
Ух.. ну

Если wilder начинает описание алгоритма работы с этих слов - значит мне вообще *****!

предельно упростим задачу:
старый объект не нужно "убивать". Он пока будет существовать, нужно просто тихо отказаться от его использования. И всю смысловую нагрузку перенести на Аккаунт. То есть нужно просто в лук-апе на станд Аккаунт прописать правильные айди соответсвующих записей, пока только на одном объекте. Есть фул-сендбок и обычные сендбоксы.

Где физически запускать этот скрипт? как боротся с лимитами?

PS: обнаружил, что у выводимого из использования объекта есть child объект - и один из самых важных, и эту связь нужно будет тоже переделывать. То есть этот child объект должен стать childом у другого объекта - стандартного Аккаунт. Еще нужно подумать как процесс такого перехода организовать, он будет явно сложнее чем просто с лук-апами...

[quote="wilder"]
Ух.. ну [/quote]

Если wilder начинает описание алгоритма работы с этих слов - значит мне вообще *****!   :( 

предельно упростим задачу:
старый объект не нужно "убивать". Он пока будет существовать, нужно просто тихо отказаться от его использования. И всю смысловую нагрузку перенести на Аккаунт. То есть нужно просто в лук-апе на станд Аккаунт прописать правильные айди соответсвующих записей, пока только на одном объекте. Есть фул-сендбок и обычные сендбоксы.

Где физически запускать этот скрипт? как боротся с лимитами?

PS: обнаружил, что у выводимого из использования объекта есть child объект - и один из самых важных, и эту связь нужно будет тоже переделывать. То есть этот child объект должен стать childом у другого объекта - стандартного Аккаунт. Еще нужно подумать как процесс такого перехода организовать, он будет явно сложнее чем просто с лук-апами...

ну если все упростить, то вот самый просто алгоритм в твоем случае.

в те объекты, которые ссылаются на твой "старый" аккаунт нужно добавить lookup поле на "новый" стандартный аккаунт. Так же я бы в "старом" аккаунт тоже добавил поле на "новый" аккаунт, чтобы не потерять связь двух копий если что.

После этого пишется батч по старым аккаунтам (это ответ на твой вопрос про лимиты).
Вот что делает батч для одной записи старого аккаунта:
- создает новую запись для нового аккаунта (копию) и вставляет в базу.
- старый аккаунт апдейтится и lookup поле заносится ссылка на новый аккаунт (теперь мы знает что эта запись отработана и для нее есть копия)
- для всех записей которые ссылаются на старый аккаунт в лукап поле на новый аккаунт сохраняется ID новой записи.

Как бы все. Смотри что получилось в итоге.
У нас появились копии аккаунтов и записи теперь ссылаются на новый и старый аккаунт.
Старая информация и связи остались, появились просто их копии.
После проверки что все ок, старые записи и ссылки можно постепенно убрать (удалить).

ну если все упростить, то вот самый просто алгоритм в твоем случае.

в те объекты, которые ссылаются на твой "старый" аккаунт нужно добавить lookup поле на "новый" стандартный аккаунт. Так же я бы в "старом" аккаунт тоже добавил поле на "новый" аккаунт, чтобы не потерять связь двух копий если что.

После этого пишется батч по старым аккаунтам (это ответ на твой вопрос про лимиты).
Вот что делает батч для одной записи старого аккаунта:
- создает новую запись для нового аккаунта (копию) и вставляет в базу.
- старый аккаунт апдейтится  и lookup поле заносится ссылка на новый аккаунт (теперь мы знает что эта запись отработана и для нее есть копия)
- для всех записей которые ссылаются на старый аккаунт в лукап поле на новый аккаунт сохраняется ID новой записи.

Как  бы все. Смотри что получилось в итоге.
У нас появились копии аккаунтов и записи теперь ссылаются на новый и старый аккаунт.
Старая информация и связи остались, появились просто их копии. 
После проверки что все ок, старые записи и ссылки  можно постепенно убрать (удалить).

Dmitry Shnyrev
Млин, сложный процесс. Wilder, и часто тебе приходилось этим заниматься?

Нет, всего 2 раза но на одном и том же проекте. Потому что заказчик был откровенный мудак. Сорри за красочное описание.

[quote="Dmitry Shnyrev"]Млин, сложный процесс. Wilder, и часто тебе приходилось этим заниматься?[/quote]
 Нет, всего 2 раза но на одном и том же проекте. Потому что заказчик был откровенный мудак. Сорри за красочное описание.

Dmitry Shnyrev
ну если все упростить, то вот самый просто алгоритм в твоем случае.

После этого пишется батч по старым аккаунтам (это ответ на твой вопрос про лимиты).
Вот что делает батч для одной записи старого аккаунта:
- создает новую запись для нового аккаунта (копию) и вставляет в базу.
- старый аккаунт апдейтится и lookup поле заносится ссылка на новый аккаунт (теперь мы знает что эта запись отработана и для нее есть копия)
- для всех записей которые ссылаются на старый аккаунт в лукап поле на новый аккаунт сохраняется ID новой записи.

Спасибо Дмитрий.

Сделать так как описывает wilder мне не разрешат, и самое главное, что я не готов к этому.

Поэтому будем разбирать "пошаговую" схему, где связанные объекта перебираются один за другим.

Твой вариант хорош, только есть отличие в начальных условиях: записи в новом аккаунт уже есть, их нужно только сопоставить по какому-то признаку со старыми.

Получился такой алгоритм:

(0) В начале нужен скрипт, который проверит, что на каждую запись старого аккаунта действительно можно найти по указанному признаку соответвующую и только одну запись в новом аккаунте.

(1) Кверим все записи нового и старого эккаунтов (не должно быть много).
(2) кверим все (или пачками по 200, или батч сам это сделает - и не нужно волноваться о лимитах) записи связанного объекта.
(3) циклом перебирает каждую запись связанного объекта,
--- и если в лук-апе на старый аккаунт есть айди, то (поправка - наличие значение в этом поле будет условием для выборки - пункт пропускаем)
--- находим эту запись в листе старых аккаунтов,
--- по ее полю-признаку находим соответствующую запись в листе новых аккаунтов,
--- засаживаем айди найденной записи в лук-ап на новый аккаунт текущей записи связанного объекта
(4) после всего апдатируем связанные записи.
(5) возможно высылаем письмо, о том, что столько-то записей было перебрано и столько из них было апдатировано.

Есть еще важный момент - связанные ДОЧЕРНИЕ объекты. Их есть у нас.

Как я понимаю, алгоритм тот же, но после этого нужно:
(1) превратить старую мастер-дитейл связь в простую лук-апную.
(2) превратить новую лук-ап связь в мастер-дитейл.
(или сначала шаг 2 затем 1).
Это возможно так трансфорировать связи?

[quote="Dmitry Shnyrev"]ну если все упростить, то вот самый просто алгоритм в твоем случае.

После этого пишется батч по старым аккаунтам (это ответ на твой вопрос про лимиты).
Вот что делает батч для одной записи старого аккаунта:
- создает новую запись для нового аккаунта (копию) и вставляет в базу.
- старый аккаунт апдейтится  и lookup поле заносится ссылка на новый аккаунт (теперь мы знает что эта запись отработана и для нее есть копия)
- для всех записей которые ссылаются на старый аккаунт в лукап поле на новый аккаунт сохраняется ID новой записи.

[/quote]

Спасибо Дмитрий.

Сделать так как описывает [b]wilder[/b] мне не разрешат, и самое главное, что я не готов к этому.

Поэтому будем разбирать "пошаговую" схему, где связанные объекта перебираются один за другим.

Твой вариант хорош, только есть отличие в начальных условиях: записи в новом аккаунт уже есть, их нужно только сопоставить по какому-то признаку со старыми.

Получился такой алгоритм:

(0) В начале нужен скрипт, который проверит, что на каждую запись старого аккаунта действительно можно найти по указанному признаку соответвующую и только одну запись в новом аккаунте.

(1) Кверим все записи нового и старого эккаунтов (не должно быть много).
(2) кверим все (или пачками по 200, или батч сам это сделает - и не нужно волноваться о лимитах) записи связанного объекта.
(3) циклом перебирает каждую запись связанного объекта, 
--- и если в лук-апе на старый аккаунт есть айди, то (поправка - наличие значение в этом поле будет условием для выборки - пункт пропускаем)
--- находим эту запись в листе старых аккаунтов,
--- по ее полю-признаку находим соответствующую запись в листе новых аккаунтов,
--- засаживаем айди найденной записи в лук-ап на новый аккаунт текущей записи связанного объекта
(4) после всего апдатируем связанные записи.
(5) возможно высылаем письмо, о том, что столько-то записей было перебрано и столько из них было апдатировано.

Есть еще важный момент - связанные ДОЧЕРНИЕ объекты. Их есть у нас.

Как я понимаю, алгоритм тот же, но после этого нужно:
(1) превратить старую мастер-дитейл связь в простую лук-апную.
(2) превратить новую лук-ап связь в мастер-дитейл.
(или сначала шаг 2 затем 1).
Это возможно так трансфорировать связи?

Сделал свой первый батч. Работает, я наблюдаю.

можно этот класс использовать для перешики связей на разных объектах, можно в аргументы передать квери, инфу с какими полями работать (они могут иметь разные названия на разных объектах), с какими объектами.

Но я не могу сообразить, как эти данные (переданные в конструктор аргументы) "вшить" в сам код.

вот например я передал в аргументы стрингом полевое API имя "MyAccount__c" но как его использовать непосредсственно в коде:

if(a.ВотСюдаНужноПодставитьЭтоНазвание == acc.ID) ...

то же самое в цикле в execute(). сейчас это так:

for (MyObject__c r : (List<MyObject__c>) scope){

как динамически заменить MyObject__c и (List<MyObject__c>) ...

это возможно? нужно ли? может есть какое то более простое решение.

Сделал свой первый батч. Работает, я наблюдаю.

можно этот класс использовать для перешики связей на разных объектах, можно в аргументы передать квери, инфу с какими полями работать (они могут иметь разные названия на разных объектах), с какими объектами.

Но я не могу сообразить, как эти данные (переданные в конструктор аргументы) "вшить" в сам  код.

вот например я передал в аргументы стрингом полевое API имя "MyAccount__c" но как его использовать непосредсственно в коде:

if(a.ВотСюдаНужноПодставитьЭтоНазвание == acc.ID) ...

то же самое в цикле в execute(). сейчас это так:

	for (MyObject__c r : (List<MyObject__c>) scope){

как динамически заменить MyObject__c и (List<MyObject__c>) ...

это возможно? нужно ли? может есть какое то более простое решение.

Вместо MyObject__c ты можешь работать с sObject
а к поля обращаться динамически или разделить куски кода с помощью if ... else ... (в каждом блоке работа с определенным объектом к типу которого приводишь из sObject)

Вместо MyObject__c ты можешь работать с sObject
а к поля обращаться динамически или разделить куски кода с помощью if ... else ... (в каждом блоке работа с определенным объектом к типу которого приводишь из sObject)