Я хотел бы отметить, что нет необходимости в денормализации, если вы готовы работать с составными первичными ключами. Образец для случая AddressEnvelop:
user(
#user_id
)
address(
#user_id
, #addres_num
)
envelope(
#user_id
, #envelope_num
)
address_envelope(
#user_id
, #addres_num
, #envelope_num
)
(# обозначает столбец первичного ключа)
Я не фанат этого дизайна, если я могу избежать этого, но, учитывая тот факт, что вы говорите, что все эти объекты привязаны к пользователю, этот тип дизайна позволит относительно просто разделить ваши данные (либо логически поместите диапазоны пользователей в отдельные таблицы или физически, используя несколько баз данных или даже машины)
Другая вещь, которая имела бы смысл в этом типе дизайна, - это использование кластеризованных индексов (в MySQL первичный ключ таблиц InnoDB создается из кластеризованного индекса). Если вы убедитесь, что user_id всегда является первым столбцом в вашем индексе, это гарантирует, что для каждой таблицы все данные для одного пользователя хранятся близко друг к другу на диске. Это замечательно, когда вы всегда делаете запрос по user_id, но это может ухудшить производительность, если вы делаете запрос по другому объекту (в этом случае лучшим решением может стать дублирование, такое как у вас sugessted)
В любом случае, прежде чем изменять дизайн, сначала убедитесь, что ваша схема уже оптимизирована, и у вас есть надлежащие индексы для столбцов внешнего ключа. Если производительность действительно имеет первостепенное значение, вам следует просто попробовать несколько решений и выполнить тесты.