Бази даних для новачка: таблиці, індекси та міграції
Де живуть дані твого сайту і як випадково не знести їх однією командою
Що таке база даних простими словами: таблиці, індекси, міграції та типи колонок. Розбираємо головні граблі вайбкодера - і як їх обійти заздалегідь.
Що таке база даних простими словами
Уяви величезну картотечну шафу зі старої бібліотеки. Усередині - шухляди (це таблиці). У кожній шухляді лежать картки (це рядки). А на кожній картці заповнені одні й ті самі поля: імʼя, дата, телефон (це колонки). Усе. Жодної магії.
Ось ця розумна шафа і є база даних База даних - місце, де застосунок зберігає все цінне: користувачів, замовлення, пости. Не зникає після перезавантаження, на відміну від того, що висить в оперативній памʼяті програми. . Усе, що твій застосунок має памʼятати назавжди - хто зареєструвався, що замовили, який пост вподобали - живе саме тут. Закрив сайт, вимкнув сервер, спіткнувся об провід і знеструмив пів кварталу - дані на місці.
А розмовляє застосунок із шафою не по-людськи, а окремою мовою - 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 гривні».
- Не проси агента «зроби базу абияк». Задавай типи, індекси та правила видалення заздалегідь.