Лучшие практики для переноса содержимого базы данных из одной очень плохой структуры в одну очень логичную? - PullRequest
17 голосов
/ 07 августа 2011

TL; DR Каков наилучший способ переноса большого количества данных между одной очень плохо структурированной базой данных (с большим количеством повторений столбцов, без взаимосвязей и дубликатов данных) в другую высокоорганизованную и реляционную структуру? - Извините за длинное чтение!

Я недавно взялся за очень сложную работу.Он переписывает всю ИТ-платформу всей компании.Боюсь, я не могу дать слишком много подробностей, потому что мы не можем дать знать старому разработчику (у него есть метафорическое оружие против головы компании, потому что он единственный, кто знает, как делать такие важные вещи, как генерация счетов,и требует все больше и больше денег).

Основная проблема заключается в том, что вся веб-платформа (используемая всем персоналом и всеми клиентами) была закодирована парнем, чьи навыки были ниже, чем у любителя .Он состоит из ~ 300 отдельных кодовых файлов.Там нет библиотеки шаблонов - все это жестко запрограммировано в каждом файле.Там нет логической структуры базы данных - она ​​была практически составлена ​​по мере его продвижения.Там нет безопасности - это шокирует.В любом случае, мы будем переписывать всю эту платформу в течение ~ 3 месяцев.

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

Один из примеров - адреса.В старой базе данных адреса используются примерно в 12 таблицах (из 44 всего ...).В нашем случае у нас есть одна таблица addresses, на которую будут ссылаться другие таблицы (например, address_id), чтобы сохранить чистоту.Основная проблема заключается в том, что примерно в половине его таблиц адреса хранятся как line1, line2, town, city и т. Д., Что хорошо, но в другой половине у него просто один address поле, в котором хранится все это!

Второй пример - даты - в некоторых таблицах он имеет даты секунды с начала эпохи, в других датах MySQL NOW(), а в других он буквально хранит их в 6столбцов в строке - year, month, day, hour, minute, second - ой ...

  • Какой хороший способ пойтио попытке решить эту проблему? Должны ли мы взглянуть на наши таблицы и выяснить, куда нам нужно вытащить его данных из наших, или мы должны обратить это и посмотреть на его таблицы и выяснить, где его данные должны войти в наши?

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

  • Скорость и эффективность запросов для нас не проблема, , поскольку нам нужно будет выполнить это только один раз (после тестирования) на наших локальных машинах.Его база данных в настоящее время составляет ~ 800 МБ, когда SQL сбрасывается, но, опять же, во многом это его бесполезные тестовые данные или просто совершенно ненужные.

Есть идеи о том, как лучше всего это решить?Для справки наша система будет переписана на PHP, поэтому любые рекомендации на основе PHP были бы хорошими.База данных в настоящее время (и все еще будет) в MySQL.

Ответы [ 5 ]

10 голосов
/ 07 августа 2011

Здесь нет решения.Нет магии.Просто тяжелая работа.

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

Вы будете иметь дело не только с простыми вопросами форматирования.У вас также будут проблемы с дублированием данных.Если у вас 12 таблиц с адресами, но только 1 клиент, какой адрес выигрывает?

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

И это подводит вас к последней проблеме.«Не теряя никаких данных» во время конвертации.

Вполне вероятно, что это не начало с первого дня, в зависимости от того, что означает «не потерять никакие данные».Например, если вы отбрасываете адреса, происходит потеря данных.Конечно, каждый компонент «имеет адрес», но не обязательно тот, который был у них раньше.Раньше они все могли быть идентичными, но и они не могут.Это будет очень грязно.

После того, как вы закончите свое отображение и другие процессы, их кодирование будет простым на большинстве языков.Языки сценариев хорошо работают для этого.Вы можете массово загрузить каждую из таблиц «как есть» в новую БД и написать процедуры хранения для выполнения преобразования.С чем бы вы ни разговаривали.Ваше преобразование, вероятно, будет состоять из нескольких этапов, и большая часть этого кода, скорее всего, будет «единственной в своем роде» исключительно для облегчения преобразования.

Это будет утомительно.Эти вещи всегда есть.Там просто слишком много деталей.Все причины, по которым это ужасная система, - причины, по которым преобразование будет ужасным.И не удивляйтесь, если у вас недостаточно времени, чтобы выделить его.

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

6 голосов
/ 07 августа 2011

Недавно я сделал несколько крупных миграций, и в течение этого постепенно разработал несколько практических лучших практик для себя.Ничего особенного в этом нет, но некоторые из них могут оказаться полезными:

Общие советы

  • Перед началом работы убедитесь, что вы понимаете существующую модель данных итребования к новой версии системы.
  • Разработайте новую схему базы данных как можно лучше и постарайтесь не напрягаться, поскольку вам потребуется перенести старый контент.
  • Используйте каркас с твердой ORM.Мало того, что будет легче разрабатывать новую версию, но и миграция будет намного проще.

Миграция

Код, связанный с миграцией данных, будетбыть частью вашего проекта в течение некоторого времени, так что это хорошая идея, чтобы выделить его пакет / папку (например, legacy).В этом пакете хранятся ваши сценарии преобразования и другие файлы, относящиеся к устаревшей системе.Через некоторое время вы сможете избавиться от него простым rm -rf legacy.

. Сценарии должны выполнять преобразование небольшими шагами.Лучше зацикливаться на таблице несколько раз и делать шаги небольшими, простыми и отлаживаемыми, чем иметь один большой скрипт, который делает все, хотя и быстрее.

Также рекомендуется запускать каждый из этапов в отдельной транзакции и выполнять фиксацию только после ее успешного завершения, чтобы вам не нужно было повторно запускать всю миграцию заново при сбое одного шага.

Весь процесс миграции, а также отдельные шаги или группы шагов должны быть выполнены с помощью одной команды из командной строки, потому что вы будете запускать ее много раз, пока не достигнете окончательной версии, поэтому чем более автоматизированы вытем лучше

Основной сценарий (т. Е. legacy/bin/full-migration) должен выполнить весь процесс (т.е. извлечь свежую копию устаревшей производственной БД, (повторно) создать новую БД и таблицы в ней, выполнить всю миграцию)и это должен быть точно такой же процесс, который вы в конечном итоге запустите после развертывания новой версии на рабочих серверах (только с другой конфигурацией).Это позволит вам тщательно протестировать его в вашей среде разработки.

Поскольку преобразование может занять много времени, полезно регистрировать каждое действие (должно делать обычное print action + object_id).Часто есть несколько строк, которые имеют некоторые неожиданные различия, которые приводят к сбою вашего скрипта или вызывают ошибку целостности ссылки.В таких случаях хорошо видеть, какой это был объект, чтобы вы могли немедленно перейти в БД, проверить данные, соответствующим образом обновить скрипт и снова выполнить неудачный шаг.

Одна вещь, которая оказалась очень полезной дляЯ должен был определить классы моделей также для устаревших таблиц баз данных, используя ORM.Я делал это пару раз в Django, который поддерживает несколько соединений с базой данных и маршрутизацию для каждой модели, поэтому я смог написать сценарии, которые выглядели примерно так (Python):

from legacy import models as old
from catalog import models as new

# Loop through all products from the legacy DB
for old_product in old.Product.objects.all():  
    # Create an instance of the new product model class
    new_product = new.Product() 
    # Copy and modify attributes as needed
    new_product.name = old_product.product_name.strip()
    # ...
    # Save it to the new database
    new_product.save()

Кроме того, чем большеограничительная новая схема лучше (т. е. NOT NULL, где это возможно, проверка внешнего ключа и т. д.), потому что она поможет вам увидеть, где ваши предположения о старой схеме неверны, а также предотвратит попадание неверных данных в вашу новую систему (InnoDB как бэкэнд для MySQL - хорошая идея).

Другая хорошая практика - сохранять старые первичные ключи в новой базе данных, где это возможно.Если после переноса вы увидите что-то странное в новых данных, вы можете вернуться и найти элемент по его идентификатору в прежней системе.

4 голосов
/ 07 августа 2011

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

Инструменты могут помочь автоматизировать процесс - но без глубокого понимания существующей системы они могут автоматизировать вас в углу.

Я бы спроектировал новую структуру данных, написал сценарии для переноса старой структуры в новую, а затем протестировал бы функциональность. Если есть проблемы, измените новую структуру и / или сценарии импорта, затем снова запустите процедуру передачи данных и повторяйте весь процесс, пока не убедитесь, что ни одна из данных или функциональность не потеряна. На этом этапе назначьте дату, чтобы закрыть старую систему, выполнить миграцию данных, а затем запустить новую систему.

Из всего этого, конечно, не хватает обучения пользователей новой / улучшенной системе. Это жизненно важно! Не оставляйте это вне вашего плана, иначе лучшая новая улучшенная улучшенная система будет потоплена из-за несчастья пользователя.

2 голосов
/ 07 августа 2011

Сначала при проектировании новой структуры включите столбцы для хранения идентификаторов записей из старой системы и таблицы, из которой она получена.Вы можете отбросить их после того, как перемещение окажется успешным, но они очень помогут в переносе данных и проверке их правильности после переноса, а также в ответах на вопросы о том, откуда поступили данные, когда пользователи удивляются увиденному.Если у старых данных нет PK, создайте их с помощью некоторого типа поля чисел.

Работа с родительскими таблицами вниз.Если адреса хранятся более чем в одном месте, определите, в каком порядке вы хотите получить адреса, и какой будет иметь приоритет, если существует несколько разных записей.Возможно, вы также захотите хранить разные адреса (таблица адресов одно-многим с таблицей person, да?), Но вам может потребоваться наличие дополнительных типов адресов.

Вам нужно разобраться с проблемами старых данных, не соответствующих новому типу данных, размеру или ограничениям (скажем, вы хотите, чтобы что-то требовалось, а они не имели значения).Решите, как вы хотите справиться, прежде чем начинать и получить выкуп от заинтересованных сторон.Возможно, вы захотите использовать значение «Неизвестно», если требуется улица 1. Если у вас есть, например, только город и штат.

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

Скорее всего, вам придется выполнить это несколько раз.Сначала на коробке разработчика, затем на коробке QA.При переходе на Prod, если процесс переноса занимает больше времени, чем вы можете себе позволить, вам может потребоваться переместить большую часть данных за один раз до запуска, а затем во время запуска просто переместить новые или измененные данные.

Предстоит проделать много работы, и для такого рода миграции 3 месяца крайне мало.Удачи.

2 голосов
/ 07 августа 2011

Одна вещь, о которой стоит подумать ...

Почему бы не спрятать новую, фиксированную, блестящую схему за представлениями, чтобы она выглядела как старая?

Это означает, что у вас есть 2 клиентахотя код базируется на одних и тех же данных, каждый из которых имеет свой собственный «API» в базе данных.

Это также означает, что старая система фактически никогда не отключается при запуске.

...