Базы данных для новичка: таблицы, индексы и миграции
Где живут данные твоего сайта и как случайно не снести их одной командой
Что такое база данных простыми словами: таблицы, индексы, миграции и типы колонок. Разбираем главные грабли вайбкодера - и как их обойти заранее.
Что такое база данных простыми словами
Представь огромный картотечный шкаф из старой библиотеки. Внутри - ящики (это таблицы). В каждом ящике лежат карточки (это строки). А на каждой карточке заполнены одни и те же поля: имя, дата, телефон (это колонки). Всё. Никакой магии.
Вот этот умный шкаф и есть база данных База данных - место, где приложение хранит всё ценное: пользователей, заказы, посты. Не исчезает после перезагрузки, в отличие от того, что висит в оперативной памяти программы. . Всё, что твоё приложение должно помнить навсегда - кто зарегистрировался, что заказали, какой пост лайкнули - живёт именно тут. Закрыл сайт, выключил сервер, споткнулся о провод и обесточил полквартала - данные на месте.
А разговаривает приложение со шкафом не по-человечески, а на отдельном языке - SQL. Это как записка библиотекарю: «принеси все карточки, где город = Москва». Зубрить SQL наизусть тебе как вайбкодеру не надо - его пишет агент или умная прослойка. Но понимать, что именно агент просит у шкафа, дико полезно. Иначе он однажды попросит «вынеси вообще всё», а ты и глазом не моргнёшь.
Зачем вайбкодеру понимать базу данных
Рано или поздно твой сайт перестанет быть красивой картинкой и захочет что-то запоминать: список заказов, аккаунты, комментарии. Вот тут и появляется база данных. А вместе с ней - целый зоопарк ошибок, от которых сайт либо тормозит, либо тихо теряет данные. Тихо - это самое противное.
Понимаешь, как устроен шкаф - и сразу выигрываешь четыре вещи:
- не паникуешь, когда агент роняет слова «миграция» и «индекс»;
- не даёшь агенту по незнанию стереть всю таблицу одной командой;
- получаешь быстрый сайт, а не такой, где список грузится по 10 секунд и пользователь успевает сбежать к конкуренту;
- ставишь задачу так, что агент делает правильно с первого раза.
Вся разница между «мой сайт иногда теряет заказы и тормозит» и «всё летает и ничего не пропадает» сводится к трём словам: тип колонки, индекс, миграция. Поехали.
Как агент работает с базой данных: четыре кита
1. Таблицы и типы колонок: форма карточки
Заводишь ящик (таблицу) - сразу для каждого поля скажи, что в нём лежит: текст, число, дата, «да/нет». Это и есть тип колонки. Промахнёшься с типом - потом переделывать долго и больно.
У опытных есть готовые правила, что чем хранить (это прямо из скилла postgres-patterns):
- Деньги - типом numeric (точное число), чтобы 0.1 + 0.2 не превратилось в 0.30000004.
- Дата и время - timestamptz (с часовым поясом), чтобы клиент с Бали и из Москвы видели верное время.
- Текст - просто text, без искусственных лимитов длины.
- Галочка да/нет - boolean, а не строка «yes»/«no».
- Деньги через float - дробные копейки уезжают в туман, бухгалтерия плачет.
- Дата через обычный текст - потом ни отсортировать, ни сравнить.
- «Да/нет» цифрой 1 и 0 или строкой - каждый раз гадаешь, что это вообще значит.
- Цена строкой «1000 руб» - ну-ка сложи такое с «990 руб».
2. Что такое индекс в базе данных
Представь телефонную книгу, где имена идут вперемешку. Чтобы найти «Петрова», ты читаешь её всю с первой страницы. Тысяча страниц - тысяча страниц чтения ради одного имени. Вот так и работает база данных без индекса. Медленно и обидно.
Индекс Индекс - служебное оглавление по колонке. База строит его заранее и потом находит нужную строку мгновенно, не перечитывая всю таблицу с начала. - это тот самый алфавитный указатель. Говоришь шкафу: «держи отдельное оглавление по полю email» - и поиск по email становится мгновенным. Без «прочитай миллион карточек и вспотей».
3. Что такое миграция базы данных
Сайт растёт, и в карточку надо добавить новое поле - скажем, «телефон». Лезть в живой шкаф руками опасно: что-нибудь да заденёшь. Поэтому изменения структуры делают миграциями Миграция - пошаговое изменение структуры базы по сохранённому чертежу: добавить колонку, создать таблицу, поставить индекс. Лежит в файлах, чтобы тот же ремонт можно было повторить на любом сервере. - записанными по шагам «чертежами ремонта».
И вот тут живёт САМАЯ опасная грабля вайбкодера. Команда, которой агенты обычно двигают эти чертежи, называется migrate dev. При определённых условиях она спрашивает разрешения стереть всю базу: если данные «не сходятся с чертежом», она обнуляет таблицы целиком (это прямо из скилла prisma-patterns). Один клик «да» - и привет.
4. Опасные команды: deleteMany и updateMany
Есть команды, которые меняют или удаляют много карточек разом. Мощные - и оттого коварные. Две главные ловушки (обе из prisma-patterns):
deleteManyбез условия стирает ВСЁ. Хотел удалить заказы одного клиента, забыл дописать «чьи именно» - и шкаф молча вынес весь ящик. Без вопросов. Без «вы точно уверены?». Без корзины.updateManyвозвращает число, а не записи. Массово что-то поменял и думаешь, что получил назад обновлённые карточки. А получил сухую цифру «изменено: 5 штук». Кто эти пятеро - выясняй отдельным запросом.
Пример из жизни: как ломается интернет-магазин
Делаешь с агентом интернет-магазинчик. Сначала всё прекрасно: пять товаров, три заказа, летает как ракета. Через месяц у тебя тысяча заказов - и вот расплата:
- Страница «мои заказы» грузится 8 секунд - потому что нет индекса по полю «покупатель», и база каждый раз перечитывает всю таблицу.
- В отчёте сумма заказа «1499.9999998» - потому что цену сохранили как float, а не
numeric. - Ты попросил агента «удали тестовые заказы», он запустил
deleteManyбез условия - и снёс все заказы, включая боевые.
Ни одна из этих бед - не «глюк ИИ». Это три понятные грабли, и все три снимаются одной грамотной постановкой задачи:
Спроектируй базу данных для интернет-магазина. Соблюдай правила:
- Цену храни точным числом для денег (numeric), НЕ дробным float.
Дату и время - с часовым поясом.
- Поставь индекс на каждое поле, по которому будем искать или
сортировать: покупатель, дата создания, статус заказа.
- Любую массовую команду удаления или обновления делай ТОЛЬКО
с условием, над какими именно записями работаем. Без условия - стоп.
- Команду migrate dev используй только локально. Для боевого сервера
готовь migrate deploy. Перед удалением чего-либо сначала покажи мне план.
- Объясни простыми словами, какие таблицы ты создал и зачем каждая.
Хитрость про скорость: курсорная пагинация
Когда список длинный (лента постов, заказы, товары), новички просят «дай мне страницу 50». Чтобы её отдать, база вынуждена отсчитать и пролистать первые 49 страниц впустую. Чем дальше страница - тем сильнее она кряхтит.
Опытные делают курсорную пагинацию Курсорная пагинация - листание по принципу «дай следующие 20 после вот этой записи», вместо «дай страницу номер 50». База не пролистывает всё с начала и работает одинаково быстро на любой глубине. : «дай 20 штук после последней показанной». Скорость одинаковая - хоть на первой странице, хоть на тысячной. Агент сам не предложил? Просто попроси: «сделай листание ленты курсором, а не по номерам страниц».
Частые ошибки новичка в базах данных
- Хранишь деньги через float. Получишь дробные копейки и кривые суммы. Только
numeric. - Забыл про индексы. На маленьких данных незаметно, на больших сайт встаёт колом. Индексируй поля поиска и сортировки.
- Запустил
migrate devна боевом сайте. Может стереть всю базу. На проде - толькоmigrate deploy. - Массово удаляешь или меняешь без условия.
deleteManyбез условия сносит всю таблицу. Всегда указывай «над кем». - Думаешь, что
updateManyвернёт записи. Он вернёт только число. Сами обновлённые карточки доставай отдельным запросом. - Не делаешь бэкап перед опасной операцией. Резервная копия - твоя машина времени. Один раз спасёт весь проект.
TL;DR - если коротко
- База данных - умный шкаф с картотекой. Таблицы - ящики, строки - карточки, колонки - поля.
- Индекс - оглавление. Нет его - база читает весь ящик ради одной карточки и дико тормозит.
- Миграция - ремонт шкафа по чертежу. `migrate dev` умеет стереть всё - ей место на твоём компе, не на проде.
- `deleteMany` без условия сносит всю таблицу. `updateMany` отдаёт число, а не сами записи. Запомни оба.
- Деньги - только точным `numeric`. Иначе однажды в корзине окажется «99.99999999 рубля».
- Не проси агента «сделай базу как-нибудь». Задавай типы, индексы и правила удаления заранее.