fedorthinks

Экспресс-курс · No. 06

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

20 понятий · схема у каждого · шпаргалка в конце

§ 01

База данных — это долговременная память твоей системы. Код переписывают; данные и форма, которую ты для них выбрал, обычно переживают всё вокруг.

Данные переживают код

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

Языки меняются, фреймворки подменяют, интерфейс перерисовывают десять раз. Данные и их структура обычно остаются, потому что менять их на живой системе, полной реальных записей, медленно и рискованно. Поэтому база — первое, о чём надо подумать всерьёз, и последнее, что стоит делать впопыхах.

База отвечает на два вопроса

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

Любое хранилище определяется двумя вещами. Первая — модель данных (data model): как оно придаёт данным форму — жёсткие таблицы, гибкие документы, граф связей. Вторая — гарантии (guarantees): строгая корректность или скорость и доступность с более слабыми обещаниями. Почти любой выбор базы — это разный ответ на эти два вопроса, и остальной курс — это меню.

Access pattern — выбирай по тому, как читаешь и пишешь

Картотечный шкаф, каталог карточек и конвейер — всё это «хранилище», но выбираешь ты по тому, как будешь доставать вещи, а не по тому, что выглядит новее.

Лучшей базы не бывает. Хранилище, идеальное под быстрые поиски по ключу, плохо для глубоких запросов по связям; построенное под огромные записи плохо для строгих банковских транзакций. Правильный вопрос — твой паттерн доступа (access pattern): что ты читаешь, что пишешь, как часто и как это должно вести себя, когда что-то идёт не так.

Карта: 20 понятий в шести группах

Карта метро: сначала видишь линии целиком, потом едешь по станциям.

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

Relational (SQL)Relational modelSQLTransactionsNoSQL familyDocumentKey-valueWide-columnGraphSpecialisedTime-seriesSearch engineVector DBObject storageGuaranteesACIDBASECAPScalingIndexReplicationShardingNormalisationChoosingPolyglot persistencePostgres first
Шесть групп понятий — по ним идут главы 2–7.

У каждого понятия дальше одно и то же: английское название (это термин, по которому его ищут в документации), образ из жизни, схема и карточка с полями: проблема, идея, пример, цена, когда брать и связи. В конце — шпаргалка на одной странице.

Код легко поменять. Данные — нет. Выбирай хранилище как решение, с которым проживёшь годы, — потому что так и будет.

§ 02

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

Relational Database — таблицы, строки и связи

Правильно сделанная таблица: каждый лист — один вид сущности (клиенты, заказы), каждая строка — одна запись, и заказы ссылаются назад на клиента, которому принадлежат.

Это понятие реляционная база данных (relational database). Она хранит данные в таблицах (tables) с фиксированной схемой (schema) и связывает таблицы по ссылке — строка заказа держит id своего клиента. Такая ссылка называется внешний ключ (foreign key). Схема — это обещание о форме: у каждого заказа есть нужные колонки, проверенные на входе. Структура заранее в обмен на здравомыслие потом.

customersidnameemail1Annann@mail.com2Bobbob@mail.comordersidcustomer_idtotal10140.0011115.5012299.00foreign keyschema = fixed columns, checked on the way inorders point back to the customer they belong to
Две таблицы: заказ хранит customer_id — внешний ключ, указывающий на клиента.
StoreRelational Database· реляционная БД, RDBMS
Проблема

Данные со структурой и связями, к которым нужно задавать разные вопросы.

Идея

Таблицы с фиксированной схемой; связи между таблицами через внешние ключи.

Пример

Postgres, MySQL: таблицы customers и orders, у заказа есть customer_id.

Цена
Схему надо продумать заранее; менять её на живых данных — работа.
Когда брать

Почти всегда как стартовая точка. Уходить — только с причиной.

Связи
Говорит на SQL, даёт Transactions и ACID.

SQL — проси что хочешь, а не как достать

Ты говоришь библиотекарю «все романы французских авторов, изданные после 1950-го, по году» — и он сам соображает, как их найти. Ты описываешь результат, а не поиск.

SQL (Structured Query Language) — это декларативный язык запросов (declarative query language): ты заявляешь нужный ответ, а база сама строит план, как его достать, включая соединение таблиц (JOIN). Этот план строит планировщик запросов (query planner). SELECT ... JOIN ... WHERE ... может ответить на вопросы, которых ты не предвидел при проектировании, — одна из тихих суперсил реляционной модели.

you write WHATSELECT title, yearFROM books JOIN authorsWHERE country = 'FR' AND year > 1950ORDER BY yearQuery plannerdecides HOWResultrowsuse indexjoin tablessort by yearthe plan is thedatabase's job
Ты пишешь, ЧТО нужно; планировщик базы решает, КАК это достать.
LanguageSQL· язык запросов
Проблема
Нужно задавать данным вопросы, не программируя каждый поиск вручную.
Идея
Описываешь результат; база сама выбирает план (индексы, соединения, сортировку).
Пример

SELECT title FROM books JOIN authors ... WHERE country = 'FR' AND year > 1950 ORDER BY year.

Цена
Сложные запросы надо уметь читать и проверять, как именно база их выполняет.
Когда брать
Везде, где есть реляционная база, — это её родной язык.
Связи
Язык Relational Database; быстрым его делают индексы (Index).

Transactions — всё или ничего

Денежный перевод — это две записи: минус здесь, плюс там, — но одно намерение. Либо обе случились, либо ни одна; наполовину сделанный перевод — катастрофа.

Это понятие транзакция (transaction): группа изменений, которая либо целиком фиксируется (commit), либо целиком откатывается (rollback), изолированно от других, и переживает падение, как только подтверждена. Набор этих обещаний называют ACID (подробно — в главе 5). Поэтому банки, заказы и склад живут в SQL — когда корректность важнее голой скорости, тебе нужно именно это обещание.

BEGINone transaction = one intentA − 100debitB + 100creditCOMMITboth savedROLLBACKneither saved✗ never: A − 100 saved, B + 100 lost
Перевод: списание и зачисление — одна транзакция. Либо COMMIT обоих, либо ROLLBACK обоих.
ConceptTransaction· транзакция
Проблема

Одно действие — это несколько записей; сбой посередине оставит мусор.

Идея
Обернуть записи в BEGIN … COMMIT: либо все сохранились, либо ни одна.
Пример
Перевод: A − 100 и B + 100 в одной транзакции.
Цена
Немного скорости и более тяжёлое масштабирование по машинам.
Когда брать
Деньги, заказы, склад — всё, где неверное число недопустимо.
Связи
Свойства транзакции и есть ACID.

Почему это правильный дефолт

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

Структурированные данные, реальные связи, произвольные запросы, сильные гарантии — реляционная база делает всё это хорошо, а современный Postgres ещё и тянет JSON, полнотекстовый поиск и даже векторы. Начинай каждый проект здесь; тянись за чем-то другим, только когда конкретная боль — масштаб, форма или паттерн доступа — выталкивает тебя.

Начинай с Postgres. Вопрос не «зачем SQL» — а есть ли у тебя реальная причина его не брать.

§ 03

Иногда жёсткая таблица — неправильная форма. «NoSQL» — это на самом деле семейство хранилищ, и каждое гнёт правила в свою сторону ради своей задачи.

Document Store — по JSON-документу на сущность

Папка заполненных анкет, где у каждой могут быть слегка разные поля — нет центрального шаблона, заставляющего все совпадать.

Это документное хранилище (document store). Оно хранит записи как гибкие JSON-подобные документы, вложенные и почти бессхемные (schema-less), так что две записи в одной коллекции (collection) могут различаться. Хорошо, когда формы разнятся или быстро меняются, и целая сущность — товар, профиль — живёт как один документ, который ты достаёшь за одно чтение.

collection: productsdocument 1{ "id": 1, "name": "Mug", "price": 12, "tags": ["kitchen"] }document 2{ "id": 2, "name": "T-shirt", "sizes": ["S", "M", "L"], "color": "blue" }different fields, same collection — no central templateone read returns the whole object
Два товара в одной коллекции с разными полями; весь товар достаётся одним чтением.
StoreDocument Store· документная БД
Проблема
Формы записей разные или быстро меняются; таблица мешает.
Идея
Каждая сущность — один вложенный JSON-документ, без общей жёсткой схемы.
Пример
MongoDB: каталог товаров, профили пользователей.
Цена
Меньше гарантий и сложнее запросы между документами, чем в SQL.
Когда брать
Сущность читается целиком, а поля у разных записей разные.
Связи

Postgres тоже умеет документы (JSONB); часто живёт по правилам BASE.

Key-Value Store — гигантская хеш-таблица

Гардероб — отдаёшь номерок, получаешь ровно своё пальто. Никаких поисков, никаких вопросов, мгновенно.

Это хранилище ключ-значение (key-value store) — простейшая форма: ключ на входе, значение на выходе, ослепительно быстро. Идеально для кэша, сессий, счётчиков ограничения запросов (rate limit) и всего, что ты достаёшь по известному id.

GET session:42by known keykey → valuesession:42{ user: 7, cart: 3 }rate:ip:1.2.3.417cache:home<html>…</html>instant, no search✗ no rich queries: “all sessions where cart > 2”
Знаешь ключ — получаешь значение мгновенно. Спросить «по значениям» нельзя.
StoreKey-Value Store· ключ-значение
Проблема
Нужно очень быстро доставать данные по известному id.
Идея
Ключ → значение, как гигантская хеш-таблица.
Пример
Redis, DynamoDB: session:42, кэш страницы, счётчик rate limit.
Цена
Искать можно только по ключу — богатых запросов по самим значениям нет.
Когда брать
Кэш, сессии, счётчики — всё, где id известен заранее.
Связи

Типичный «быстрый помощник» рядом с основной базой в Polyglot persistence.

Wide-Column Store — под огромные потоки записей

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

Это хранилище широких колонок (wide-column store). Оно размазывает данные по множеству машин по ключу партиции (partition key) ради огромной пропускной способности записи и масштаба, меняя богатые запросы и строгую согласованность на способность принять брандспойт данных. Мощно — и больше работы по эксплуатации.

app 1writesapp 2writesapp 3writeshash(key)partition keyNode 1user:7 → t1 · t2 · t3 · t4 · …Node 2user:10 → t1 · t2 · t3 · t4 · …Node 3user:13 → t1 · t2 · t3 · t4 · …Node 4user:16 → t1 · t2 · t3 · t4 · …writes spread across many machines · wide rows · no joins
Ключ партиции раскидывает записи по многим машинам; строки длинные, соединений нет.
StoreWide-Column Store· широкие колонки
Проблема
Записей так много, что одна SQL-машина прогнётся.
Идея
Разложить данные по многим узлам по ключу партиции; писать параллельно.
Пример
Cassandra: логи событий, телеметрия, ленты на большом масштабе.
Цена
Нет богатых запросов и строгой согласованности; сложнее эксплуатировать.
Когда брать
Брандспойт записей, а запросы заранее известны и простые.
Связи
По сути встроенный Sharding; обычно живёт по BASE.

Graph Database — когда суть в связях

Доска детектива — фото, соединённые нитями. Ценность не в отдельном фото, а в паутине того, кто с кем связан.

Это графовая база данных (graph database). Она моделирует данные как узлы (nodes) и рёбра (edges) между ними, делая запросы по связям — «друзья друзей, которым это нравится», «путь между этими двумя аккаунтами» — естественными и быстрыми там, где SQL понадобились бы болезненные многосторонние соединения. Тянись за этим, когда связи важнее самих записей.

FRIENDFRIENDFRIENDWORKS_WITHLIKESAnnBobDanCaraJazz clubplace“friends of friends who like X” = follow the edges, no joins
«Друзья друзей, которым нравится X»: просто идём по рёбрам Ann → Bob → Cara → Jazz club.
StoreGraph Database· графовая БД
Проблема
Главные вопросы — про связи, и в SQL это многоэтажные JOIN.
Идея
Узлы и рёбра — первоклассные данные; запрос идёт по рёбрам.
Пример
Neo4j: социальный граф, рекомендации, выявление мошенничества.
Цена
Узкая ниша; для обычных записей и отчётов неудобна.
Когда брать
Связи важнее самих записей.
Связи
Альтернатива Relational Database, когда JOIN становится болью.

NoSQL — это не «новее SQL». Каждое хранилище сбрасывает какую-то гарантию ради чего-то конкретного — знай, чем именно ты жертвуешь.

§ 04

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

Time-Series Database — данные со штампом времени

Лента кардиомонитора — бесконечная полоса показаний, каждое привязано к моменту, и ты почти всегда спрашиваешь «что было между этими двумя временами?»

Это база временных рядов (time-series database). Она заточена под данные, которые приходят по порядку времени и запрашиваются по времени — метрики, показания датчиков, цены. Принимает огромные потоки и быстро отвечает «среднее за минуту за прошлую неделю», со встроенным удалением старых данных (retention).

expired(retention)WHERE time BETWEEN t1 AND t2t1t2time →readings arrive in time order and are asked about by time
Точки идут по времени; запрос — окно от t1 до t2; старое удаляется по retention.
StoreTime-Series Database· временные ряды, TSDB
Проблема
Огромный поток показаний, и все вопросы — «что было за этот период».
Идея
Хранить и индексировать по времени; быстро агрегировать окна.
Пример
InfluxDB, TimescaleDB: метрики серверов, датчики, цены.
Цена
Ещё одно хранилище; для обычных бизнес-данных не подходит.
Когда брать
У всего есть метка времени, и время — главная ось.
Связи
TimescaleDB — расширение Postgres, см. Postgres first.

Search Engine — полный текст и релевантность

Строка поиска, которая прощает опечатки, ставит лучшие совпадения первыми и находит «running», когда ты набрал «run», — как библиотекарь, понимающий, что ты имел в виду.

Это поисковый движок (search engine). Он строит обратный индекс (inverted index) — «слово → документы» — ради быстрого полнотекстового поиска (full-text search) с ранжированием, нечётким совпадением и фильтрами — того, что LIKE '%word%' в SQL делает медленно и плохо. Обычно работает рядом с основной базой, держится в синхроне и питает строку поиска и разбор логов.

Postgressource of truthSearch indexElasticsearch“runing shoe”typo + stemmingsyncqueryinverted indexrun → doc 3, doc 7shoe → doc 7, doc 9red → doc 3ranked results1. doc 7 · 0.922. doc 3 · 0.613. doc 9 · 0.40a fast lens onto the data — not the source of truth
Данные копируются из Postgres в поисковый индекс; запрос с опечаткой даёт ранжированный список.
StoreSearch Engine· поисковый движок
Проблема
LIKE '%word%' медленный, не прощает опечаток и не ранжирует.
Идея
Обратный индекс слов + оценка релевантности.
Пример
Elasticsearch, OpenSearch: строка поиска на сайте, разбор логов.
Цена
Надо держать в синхроне с основной базой.
Когда брать
Пользователи ищут по тексту и ждут «умного» поиска.
Связи

Не источник правды — быстрая линза на него; часть Polyglot persistence.

Vector Database — поиск по смыслу

Вместо совпадения точных слов ты спрашиваешь «найди то, что похоже на это» — и получаешь соседей по сходству, а не по ключевому слову.

Это векторная база данных (vector database). Она хранит embeddings — числовые отпечатки смысла — и находит ближайшие (nearest neighbours), так что ты ищешь по сходству, а не по точному тексту. Это движок под семантическим поиском (semantic search) и RAG, где AI-приложение достаёт самые релевантные куски, чтобы из них ответить.

“refund policy”query textEmbedding modeltext → numbers[0.12, −0.83, …]vectorrefunds FAQreturnsmoney backpricingcareersoffice mapAPI docsnearest neighbours = closest in meaning
Текст превращается в вектор; ближайшие точки — это тексты, близкие по смыслу.
StoreVector Database· векторная БД
Проблема
Нужно найти похожее по смыслу, а слова могут не совпадать.
Идея
Хранить embeddings и искать ближайших соседей.
Пример

pgvector, Pinecone: по запросу «refund policy» найти «returns» и «money back».

Цена
Нужна модель embeddings и синхронизация с исходными данными.
Когда брать

Семантический поиск и RAG — новое обязательное хранилище эпохи AI.

Связи
pgvector — расширение Postgres; копия данных, как Search Engine.

Object Storage — куда кладут большие файлы

Бокс на складе самообслуживания — не для карточек, а для мебели: громоздкие вещи, которые держишь по ярлыку и вывозишь целиком.

Это объектное хранилище (object storage). Оно не база данных, но именно туда кладут большие блобы (blobs) — картинки, видео, бэкапы, документы — адресуемые ключом (key) внутри бакета (bucket) и отдаваемые дёшево на масштабе. Паттерн почти универсален: файл — в объектном хранилище, а строку, указывающую на него, — в базе. Записи в БД, нагрузка в бакете.

photos (Postgres)iduser_ids3_key17photos/7/a1.jpg29videos/9/b2.mp4S3 bucketphotos/7/a1.jpg4.2 MB · imagevideos/9/b2.mp4310 MB · videobackups/db.tar12 GB · backuprecords in the DBpayloads in the bucket
Строка в Postgres хранит только ключ; сам файл лежит в S3-бакете.
StoreObject Storage· объектное хранилище, S3
Проблема
Большие файлы в базе раздувают её и дорого отдаются.
Идея
Файл — в бакете по ключу; в базе — только строка с этим ключом.
Пример
S3 и его собратья: фото, видео, бэкапы, документы.
Цена

Не база: запросов по содержимому нет, только «положить/достать по ключу».

Когда брать
Любые большие файлы.
Связи
По форме похоже на Key-Value Store, только для громоздких вещей.

Не выгибай основную базу в поисковый движок или файловый сервер. Специализированную задачу клади в хранилище, построенное под неё.

§ 05

Самый глубокий выбор базы — не её форма, а то, что она обещает, когда что-то идёт не так. Небольшой алфавитный суп называет этот размен.

ACID — пессимистично, корректно, осторожно

Кассир в банке, который перепроверяет каждую запись и не двинется дальше, пока книги не сойдутся, — медленнее, зато никогда не ошибается.

ACID — это строгое обещание реляционных баз о транзакциях: каждая транзакция оставляет данные корректными и полными или не происходит вовсе. Четыре буквы: Atomicity (всё или ничего), Consistency (правила данных всегда соблюдены), Isolation (параллельные транзакции не мешают друг другу), Durability (подтверждённое переживает падение). Для денег, заказов и всего, где неверное число недопустимо, это тот размен, что тебе нужен.

AAtomicityall or nothingCConsistencyrules always holdIIsolationno cross-talkDDurabilitysurvives a crashthe strict promise — for money, orders, inventory
Четыре буквы ACID и что каждая обещает.
GuaranteeACID· Atomicity, Consistency, Isolation, Durability
Что обещает
Каждая транзакция целиком корректна или не случилась вовсе.
Пример
Банковский перевод, оформление заказа, списание со склада.
Цена
Некоторая скорость и более тяжёлое масштабирование по машинам.
Когда брать
Неверное число недопустимо.
Связи
Свойства Transaction; противоположная позиция — BASE.

BASE — оптимистично, доступно, в итоге верно

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

Многие NoSQL-системы занимают противоположную позицию: BASE (Basically Available, Soft state, Eventually consistent). Они остаются быстрыми и доступными и принимают, что копии данных могут ненадолго расходиться, прежде чем сойтись. Это называется согласованность в конечном счёте (eventual consistency).

copies briefly disagreeNode Alikes 10likes 11Node Blikes 10likes 11Node Clikes 10likes 11Convergedeventuallyfast and available now, consistent a moment later
Запись попала на узел A сразу, на B и C — чуть позже. Миг расхождения, потом все согласны.
GuaranteeBASE· Basically Available, Soft state, Eventually consistent
Что обещает
Система всегда отвечает; копии сходятся «в итоге».
Пример
Счётчик лайков, лента, счётчик просмотров.
Цена
Можно ненадолго увидеть устаревшее значение.
Когда брать

Доступность важнее мгновенной точности, и секунда устаревания ничего не стоит.

Связи
Противоположность ACID; выбор «A» в CAP.

CAP Theorem — при обрыве сети выбирай

Команда, разрезанная упавшей телефонной линией: каждая половина может работать сама (но они разойдутся) или сложить инструменты до восстановления связи (но ты встаёшь). И то, и другое сразу — нельзя.

Теорема CAP (CAP theorem) говорит: когда сетевой раздел (network partition) разрезает машины твоей базы, ты должен выбрать Consistency (отказывать в записи, оставаться корректным) или Availability (продолжать обслуживать, рискуя расхождением) — оба сразу во время раздела невозможны. Любая распределённая база делает этот выбор. Знать, что выбирает твоё хранилище, — значит знать, как оно ведёт себя в худший день.

Node 1has dataNode 2has data✗partitionthe network split — pick one:CP — Consistencyrefuse writes, stay correctAP — Availabilitykeep serving, may divergecost: downtimecost: stale or conflicting data
Сеть порвалась: либо CP (отказываем, но корректны), либо AP (работаем, но можем разойтись).
TheoremCAP Theorem· Consistency, Availability, Partition tolerance
Что говорит

При разрыве сети нельзя одновременно быть и корректным, и доступным.

Пример

Два узла потеряли связь: отказать в записи (CP) или принять её на обоих и потом мирить (AP).

Цена
CP — простой; AP — устаревшие или конфликтующие данные.
Когда думать
Как только данные живут больше чем на одной машине.
Связи
Встаёт из-за Replication и Sharding; AP-сторона — это BASE.

ACID для денег, BASE для лайков. Нужная гарантия задаётся ценой того, чтобы ненадолго ошибиться.

§ 06

Горстка приёмов превращает базу из одной хрупкой коробки в нечто быстрое и живучее. Со всеми ты столкнёшься.

Index — предметный указатель для данных

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

Индекс (index) — это побочная структура, превращающая полный перебор таблицы (full table scan) в прямой поиск, самый большой рычаг скорости чтения. Подвох: каждый индекс стоит места и замедляет записи (каждая вставка должна обновить и его).

WITHOUT INDEXreadallWITH INDEXann@…bob@…cara@…dan@…eve@…sorted lookuptable rowsfast reads · but costs space and slows every write
Без индекса база читает все строки; с индексом — прыгает по отсортированному списку прямо к нужной.
TechniqueIndex· индекс
Проблема
Запрос читает всю таблицу, и с ростом данных становится медленным.
Идея
Отсортированная побочная структура по колонке → прямой поиск строки.
Пример
Индекс по email: найти пользователя — без перебора всей таблицы.
Цена
Место на диске и медленнее каждая запись.
Когда брать

На колонки, по которым реально фильтруешь и сортируешь, — не на все подряд.

Связи
Ускоряет SQL; поисковый движок — это особый индекс по тексту.

Replication — держи копии, переживай отказ

Документ, хранимый в трёх сейфах в трёх зданиях — если одно сгорит, другие всё равно держат его, и трое могут читать одновременно.

Репликация (replication) держит копии данных на нескольких машинах. Все записи идут в лидера (leader), а реплики (followers, replicas) получают копию и обслуживают чтения. Если лидер умирает, его место занимает реплика (failover). Подвох — лаг репликации (replication lag): реплика может отставать на миг, так что только что записанное значение может ещё не показаться на ней.

AppwritesLeaderall writesFollower 1serves readsFollower 2serves readsFollower 3serves readscopylag: a moment behindleader dies → a follower takes oversame data, many machines: survive failure, spread reads
Лидер принимает записи и рассылает копии; реплики отдают чтения и подхватывают, если лидер упал.
TechniqueReplication· репликация, leader–follower
Проблема
Одна машина — одна точка отказа и предел по чтениям.
Идея
Те же данные на нескольких машинах: лидер пишет, реплики читают.
Пример

Postgres с двумя репликами для чтения; при падении лидера реплика становится лидером.

Цена
Лаг: свежая запись может ещё не дойти до реплики.
Когда брать
Нужна надёжность или чтений больше, чем тянет одна машина.
Связи

Копирует одни и те же данные; Sharding делит разные. Обе ведут к CAP.

Sharding — дели, когда одной машины мало

Один переполненный картотечный шкаф становится A–M в одном шкафу и N–Z в другом. Больше места — но теперь надо знать, в каком шкафу живёт имя.

Когда данные или нагрузка на запись перерастают одну машину, шардинг (sharding) делит данные по многим — пользователи A–M здесь, N–Z там. Каждая часть называется шард (shard), а поле, по которому делим, — ключ шардирования (shard key). Это открывает почти безграничный масштаб, но ключ шардирования — тяжёлый, почти необратимый выбор: ошибёшься — получишь горячие точки (hotspots) или запросы, которым приходится бить по всем шардам.

AppRoutershard key: nameShard 1users A–MShard 2users N–Z“Ann”“Zoe”different data on eachbad key → hotspots, or queries that hit every shard
Роутер смотрит на ключ: «Ann» — в шард 1, «Zoe» — в шард 2. На каждом шарде разные данные.
TechniqueSharding· шардинг, горизонтальное партиционирование
Проблема
Данные или поток записей не помещаются в одну машину.
Идея
Разделить данные по ключу между многими машинами.
Пример
Пользователи A–M на шарде 1, N–Z на шарде 2.
Цена

Ключ почти не поменять; плохой ключ → горячие точки или запросы по всем шардам.

Когда брать
Последним: после индексов и реплик.
Связи

Встроен в Wide-Column Store; вместе с Replication ведёт к CAP.

Normalization / Denormalization — один факт в одном месте или копии ради скорости

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

Нормализация (normalization) держит каждый факт ровно в одном месте — чисто, без противоречий, реляционный дефолт. Денормализация (denormalization) намеренно дублирует данные, чтобы чтения были быстрее и требовали меньше соединений. Оба подхода годятся; правило — делать это осознанно и всегда знать, какая копия источник правды (source of truth), а какая просто быстрый дубль. (Тот же урок, что с кэшем.)

NORMALISEDorder 10order 11order 12address #51 Main StDENORMALISEDorder 10 · 1 Main Storder 11 · 1 Main Storder 12 · 1 Main Steach fact in one place · needs joinsfast reads · copies to keep honest
Слева все заказы ссылаются на один адрес; справа адрес скопирован в каждый заказ.
TechniqueNormalization / Denormalization· нормализация / денормализация
Проблема

Один и тот же факт в нескольких местах расходится; а соединения замедляют чтения.

Идея
Нормализуй по умолчанию; денормализуй осознанно там, где чтения важнее.
Пример
Адрес в одной таблице addresses против копии адреса в каждом заказе.
Цена

Нормализация — больше JOIN; денормализация — копии, которые надо синхронизировать.

Когда брать
Денормализацию — когда измеренно медленные чтения требуют этого.
Связи

Та же идея «источник правды + быстрые копии», что в Polyglot persistence.

Сначала индекс, потом сервер; сначала реплика, потом шард. Самое дешёвое масштабирование — то, которое не приходится эксплуатировать.

§ 07

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

Polyglot Persistence — несколько хранилищ осознанно

На кухне есть холодильник, морозилка и кладовка — а не одна коробка, заставленная делать всё три. Каждая держит то, что ей подходит.

Это паттерн Polyglot persistence — «многоязычное хранение». Зрелые системы обычно используют несколько хранилищ: Postgres как источник правды, Redis для кэша и сессий, поисковый индекс для строки поиска, может быть, векторное хранилище для AI-фич и объектное хранилище для файлов. Каждое делает то, в чём хорошо. Дисциплина в том, чтобы ясно держать, какое из них хранит правду, а остальные — быстрые копии, держащиеся в синхроне.

Your appPostgressource of truthRediscache · sessionsSearchsearch barVector DBAI featuresS3filesdashed = fast copies kept in sync from the source of truth
Пять хранилищ, каждое под свою задачу. Правда — в Postgres, остальное — копии.
PatternPolyglot Persistence· несколько хранилищ в одной системе
Проблема
Одна база не может быть лучшей во всём сразу.
Идея
Каждой задаче — своё хранилище; один явный источник правды.
Пример
Postgres + Redis + поисковый индекс + векторное хранилище + S3.
Цена
Каждое хранилище надо эксплуатировать, бэкапить и держать согласованным.
Когда брать

Когда реальная боль требует ещё одного хранилища, а не «на всякий случай».

Связи
Начинается с Postgres first; объединяет почти все хранилища курса.

Postgres First — начинай с Postgres, вырастай осознанно

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

Это практика Postgres first. Современный Postgres поразительно способен — реляционное ядро, JSON-документы, полнотекстовый поиск, векторы, даже рабочая очередь задач. Большинство продуктов должны начинать просто с Postgres и добавлять специализированное хранилище, только когда реальная, измеренная боль этого требует. Каждая лишняя база — это ещё одно, что надо эксплуатировать, бэкапить и держать согласованным. Самое дешёвое хранилище — то, которое ты не добавил.

Postgresone store to runRelationaltables + SQLJSONBdocumentsFull-text searchtsvectorpgvectorembeddingsJob queueSKIP LOCKED+ Redis, Elastic…only on measured painstart here · add a store only when a real pain demands it
Один Postgres закрывает таблицы, документы, поиск, векторы и очередь. Новое хранилище — только по реальной боли.
PracticePostgres First· начинай с Postgres
Проблема
Команда добавляет базы раньше, чем появляется боль.
Идея
Один Postgres, пока измеренная проблема не потребует большего.
Пример

JSONB вместо отдельной документной базы, pgvector вместо отдельной векторной.

Цена
На очень большом масштабе специализированный движок всё же обгонит.
Когда брать
В начале почти любого продукта.
Связи
Первый шаг к Polyglot persistence — когда «пока что» закончилось.

Как всё связано

Карта района после прогулки: теперь видно, какие улицы куда ведут.

Понятия курса не живут поодиночке. Реляционная база — источник правды с гарантиями ACID; индекс ускоряет её чтения; поисковый движок и векторная база — копии, которые от неё питаются; в объектном хранилище лежат файлы, на которые указывают её строки. Когда одной машины мало, приходят репликация и шардинг — и вместе с ними выбор CAP. NoSQL-семейство часто выбирает BASE — противоположность ACID.

Search enginesynced copyVector DBsynced copyObject storagefiles by keyIndexspeeds readsRelational DBsource of truth · ACIDScale-outreplicas · shardsNoSQL familydoc · KV · wide · graphBASEeventually consistentCAPC or A on a splitfeedsfeedsrows point togrowsforcesoftenopposite of ACID
Главные связи между понятиями курса: в центре — источник правды.
Прежде чем выбрать базу
  • Какой формы данные — таблицы, документы, ключ-значение, граф?
  • Как я буду их запрашивать — по id, по связям, по тексту, по сходству, по времени?
  • Какие гарантии мне нужны — строгий ACID или сойдёт eventually consistent?
  • Каков баланс чтений/записей и примерный масштаб?
  • Не смог бы Postgres уже это сделать, прежде чем я добавлю ещё хранилище?
  • Какое хранилище держит источник правды, а какие — просто копии?
Признаки, что ты выбрал не то
  • Ты гоняешь LIKE '%...%' для поиска вместо поискового движка.
  • Хранилище ключ-значение там, где постоянно нужно запрашивать по значениям.
  • Пять баз для продукта, который поддерживают два человека.
  • Ты взял MongoDB, чтобы избежать схем, а потом всё равно руками собрал валидацию.
  • Нет ясного источника правды — два хранилища оба претендуют на авторитет.
Признаки, что ты выбрал хорошо
  • Запрос, который ты гоняешь чаще всего, — тот, в котором хранилище быстрее всего.
  • Гарантия соответствует ставкам — строгая для денег, расслабленная для лайков.
  • Ты можешь назвать источник правды для каждого важного факта.
  • Ты добавил каждое хранилище, чтобы решить реальную, прочувствованную боль, а не гипотетическую.
  • Ты мог бы объяснить модель данных новому инженеру за несколько минут.

Шпаргалка: все 20 понятий

Реляционная основа

Relational Databaseреляционная БД

Таблицы с фиксированной схемой, связи через внешние ключи. Дефолт.

SQLязык запросов

Описываешь, что нужно; база сама решает, как достать.

Transactionтранзакция

Несколько записей как одно целое: COMMIT всех или ROLLBACK всех.

Семейство NoSQL

Document Storeдокументная БД

Гибкие JSON-документы; сущность читается целиком.

Key-Value Storeключ-значение

Ключ → значение, мгновенно. Кэш, сессии, счётчики.

Wide-Column Storeширокие колонки

Данные по многим машинам ради брандспойта записей.

Graph Databaseграфовая БД

Узлы и рёбра; запросы по связям без мучительных JOIN.

Специализированные хранилища

Time-Series Databaseвременные ряды

Показания по времени; запросы окнами, старое удаляется.

Search Engineпоисковый движок

Полнотекстовый поиск с ранжированием и опечатками. Копия, не правда.

Vector Databaseвекторная БД

Embeddings и поиск ближайших по смыслу. Основа RAG.

Object StorageS3

Большие файлы по ключу в бакете; в базе — только ссылка.

Гарантии

ACIDстрогое обещание

Транзакция целиком корректна или не случилась. Для денег.

BASEeventual consistency

Всегда доступно, копии сходятся в итоге. Для лайков.

CAP Theoremтеорема CAP

При разрыве сети — либо корректность, либо доступность.

Масштаб

Indexиндекс

Указатель для быстрого чтения; цена — место и медленные записи.

Replicationрепликация

Те же данные на многих машинах: надёжность и чтения. Есть лаг.

Shardingшардинг

Разные данные на разных машинах по ключу. Ключ почти не поменять.

Normalization / Denormalizationнормализация

Один факт в одном месте — или осознанные копии ради скорости.

Как выбирать

Polyglot Persistenceнесколько хранилищ

Каждой задаче своё хранилище, один источник правды.

Postgres Firstначинай с Postgres

Один Postgres, пока реальная боль не потребует большего.

Лучшее решение по базе обычно — «Postgres, пока что» — плюс мудрость понять ровно тот момент, когда «пока что» закончилось.

Конец экспресс-курса · 7 глав · 20 понятий

Дальше — глубина: «Designing Data-Intensive Applications» Мартина Клеппманна — та самая книга, которую стоит прочесть, плюс документация Postgres и руководство твоего хранилища. Но прежде глубокой воды — представь, как твои данные будут читать, писать и кому доверять. База — это место, где система помнит; выбери, как она помнит, прежде чем выбирать, на чём она построена.