Ответ
Да, несколько раз. Чаще всего это было связано с ростом нагрузки и изменением бизнес-требований.
Например, в одном из проектов изначально использовалась денормализованная схема, где данные заказов хранились в JSON-поле таблицы пользователей. При увеличении объема данных и необходимости сложных аналитических запросов это стало узким местом. Мы провели нормализацию до третьей нормальной формы (3NF), выделив заказы в отдельную таблицу и настроив индексы.
Пример рефакторинга:
-- Было: плохая нормализация
CREATE TABLE users (
id INT,
name VARCHAR(100),
order_details TEXT -- JSON-массив заказов
);
-- Стало: нормализованная схема
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(100)
);
CREATE TABLE orders (
id INT PRIMARY KEY,
user_id INT,
details TEXT,
created_at TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);
CREATE INDEX idx_orders_user_id ON orders(user_id);
CREATE INDEX idx_orders_created_at ON orders(created_at);
Основные причины перепроектирования в моем опыте:
- Производительность: медленные запросы из-за отсутствия индексов или неоптимальной схемы.
- Новые требования: бизнесу потребовались отчеты, которые было невозможно построить на старой структуре.
- Масштабирование: подготовка к шардингу или репликации.
- Целостность данных: внедрение FOREIGN KEY и CHECK-ограничений, которых изначально не было.
Перед внедрением в production мы всегда тестировали изменения на staging-окружении с копией реальных данных, проводили нагрузочное тестирование и планировали миграцию с минимальным временем простоя.
Ответ 18+ 🔞
Да ты что, серьёзно спрашиваешь? Ну конечно, блядь, бывало, и не раз! Это ж как с машиной — сначала купил жигули, а потом понял, что жрёт бензина дохуя, да и в горку не тянет. Вот и с базой так же.
Чаще всего всё упиралось в то, что нагрузка подскакивала, как сумасшедшая, или бизнес приходил с новыми хотелками, от которых волосы дыбом встают. Вот, например, был у меня проект, где поначалу схема была денормализованная так, что мама не горюй. Данные по заказам тупо пихали в JSON-поле прямо в таблице пользователей. Пока данных было мало — работало. А как объёмы подросли и понадобились сложные отчёты — всё, приехали. Узкое место, пиздец. Пришлось нормализовать всё до третьей нормальной формы, выносить заказы в отдельную таблицу и индексы настраивать, чтобы хоть как-то ожило.
Смотри, как примерно переделывали:
-- Было: пиздец, а не нормализация
CREATE TABLE users (
id INT,
name VARCHAR(100),
order_details TEXT -- JSON-массив заказов
);
-- Стало: более-менее человеческая схема
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(100)
);
CREATE TABLE orders (
id INT PRIMARY KEY,
user_id INT,
details TEXT,
created_at TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);
CREATE INDEX idx_orders_user_id ON orders(user_id);
CREATE INDEX idx_orders_created_at ON orders(created_at);
А вообще, основные причины, из-за которых приходилось всё ломать и переделывать, были такие:
- Производительность ебаная. Запросы начинают тормозить так, что терпения ноль, ебать. Потому что индексов нет или схема кривая.
- Новые требования. Приходят бизнес-аналитики с глазами, полными надежды, и хотят отчёты, которые на старой структуре построить — просто хуй с горы.
- Масштабирование. Надо готовить систему к тому, что данных станет овердохуища, и думать про шардинг или репликацию.
- Целостность данных. Осознаёшь, что пора бы уже FOREIGN KEY навесить, а то какой-нибудь распиздяй уже накосячил с данными.
Ну и, ясное дело, перед тем как в продакшн это дело пихать, мы всё на staging-окружении тестировали, на реальных данных копиях гоняли, нагрузку имитировали. План миграции писали так, чтобы время простоя было минимальным, а то мало ли — волнение, ебать.