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

Привет, Хабр! Я Владимир Комаров — программист, администратор, архитектор данных и инфраструктуры, преподаватель и автор. В этой статье по мотивам моего доклада на Highload++ мы посмотрим, как развивались системы управления базами данных: с чего всё начиналось, как система хранения данных СУБД эволюционировала, и в каком состоянии эта область находится сейчас. А заодно узнаем, существует ли идеальная СУБД, и если нет, то как приблизиться к идеалу.

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

Выше пример таких ограничений. Если вкратце, то:

  • сервер оборудован единственным вычислительным модулем,

  • скромный объём памяти, в который данные не помещаются (максимум — кэш),

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

Согласитесь, это не похоже на современное оборудование. И возникает закономерный вопрос: зачем я беру такие старые примеры? И второй вопрос — со звёздочкой: прежде, чем продолжите читать, попытайтесь отгадать, на какой год актуальны эти ограничения?

Немного истории: рождение традиционных СУБД

Чтобы понять, почему современные СУБД устроены именно так, нужно посмотреть, с чего всё начиналось:

  • Ingres — проект, из которого позже вырос Postgres, а под его влиянием были созданы Sybase и SQL Server, — 1974 год.

  • System R, которую часто называют старейшей реляционной СУБД, хотя это не совсем так, — 1975 год.

  • Oracle — до сих пор база данных №1 в мире, как они сами любят шутить, — 1979 год.

Конечно, за прошедшие десятилетия эти платформы развивались. Но если взглянуть с высоты птичьего полёта, то именно система ввода-вывода архитектурно осталась той же самой.

Ввод-вывод традиционной СУБД: как это устроено

Все данные разбиты на страницы фиксированного размера — как правило, по восемь килобайт (хотя встречаются и другие варианты). Если процессу нужны какие-то данные, он считывает с диска соответствующую страницу и помещает её в буферный кэш. Это огромный массив, занимающий практически всю доступную память, которая остаётся после операционной системы и кода экземпляра базы данных. Буферный кэш также разбит на страницы того же размера, что и данные на диске, и обмен идёт только страницами — нельзя прочитать или записать половину.

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

Чтобы при аварии данные не потерялись, ведётся журнал. Запись в него только последовательная. В современных реализациях его практически никогда не читают — исключение составляют случаи репликации или восстановления данных после сбоя. Хотя создатели документа ARIES, на основании которого и разработана архитектура ранних СУБД, предполагали, что журнал можно будет и читать.

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

Признаюсь: данные в таблице выше актуальны на 1985 год. Только-только появился SPARC, причём в спецификации v7, а не v9. Топовая комплектация сервера Sun 4 (ещё даже не SunFire) включала всего 128 МБ памяти. В этом же году появился процессор Intel 80386, и никому и в голову не приходило, что его потомки станут основой не только для десктопов, но и для серверной инфраструктуры.

Изменения характеристик сервера БД

Но самое интересное не то, что мощность всех компонентов выросла, а то, что она выросла крайне неравномерно. Например, время доступа к памяти уменьшилось всего лишь в пять раз, а тактовая частота процессора выросла в 200 раз. Сеть ускорилась в тысячу раз, а диски — в десять тысяч.

И это только те изменения, которые легко оцифровать. Но есть и такие, которые выразить в цифрах сложнее.

1. Процессоры

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

2. Диски

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

3. Сеть

Сеть не только ускорилась, она совсем по-другому масштабируется. Если 40 лет назад тысяча узлов считалась уровнем enterprise-класса с дорогим оборудованием и сертифицированными специалистами, то сегодня это железо, купленное со скидкой на маркетплейсе, и толковый студент, который его поднимет.

Предел производительности

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

Это значит, что узким местом в этой архитектуре становится уже не оборудование. Давайте посмотрим, что именно.

Конкуренция за страницы в памяти (spin-lock)

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

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

Вместо этого заводится переменная, обозначающая блокировку, и если атомарной операцией установить её значение не удалось, процесс ждёт. Но отдавать на время ожидания управление операционной системе долго и дорого, поэтому ожидающий поток просто крутится в пустом цикле. Такая конструкция называется spin-lock, а Oracle, у которого традиционно своя терминология, называет это latch. Теперь представьте: 64 быстрых ядра с конвейерами и кэшем на высокой тактовой частоте наперегонки крутят пустые циклы. Зрелище, прямо скажем, душераздирающее…

Перерасход памяти (работа с целыми страницами)

Вторая проблема — нерациональный расход памяти.

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

Большой объём журнала

И, наконец, третья проблема — журнал. Казалось бы, туда достаточно записать ключ и изменяемое значение, и журнал будет компактным.

Но в этой архитектуре нужно фиксировать ещё и физическое изменение страницы.

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

Я с огромным удовольствием слушал доклад Андрея Бородина на конференции PgConf.2025. Он рассказывал, что любое уменьшение журнала хотя бы на несколько процентов — это уже огромное достижение.

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

Ограничение по типу нагрузки

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

Мечта всех потребителей — это гибридная транзакционно-аналитическая база данных (HTAP). Долгое время все заявления о том, что база действительно гибридная, были не более чем маркетинговыми спекуляциями. Но ситуация изменилась, и чуть позже мы это увидим.

Поиск новой архитектуры

XX век был периодом безусловного доминирования традиционных СУБД, но рост объёмов данных и эволюция серверного оборудования заставили инженеров искать новые подходы. В XXI веке появляются принципиально другие решения, которые пробуют обойти ограничения классической архитектуры.

In-memory базы

В начале XXI века появились распределённые key-value хранилища (Cassandra, Riak, MongoDB), но останавливаться на них не буду, потому что в их архитектуре нет ничего, что хотелось бы  взять с собой в «светлое будущее».

А вот 2010-е годы — уже интереснее. Это время расцвета баз данных в памяти. Первые такие решения для особо богатых клиентов появились ещё в конце XX века, но именно в десятые начался их массовый рост. Главная идея проста: использовать оперативную память не как кэш, а как основное хранилище. Данные можно хранить гораздо компактнее, уместить в память больше информации и эффективнее к ней обращаться.

Однако вскоре выяснилось, что это решение не так эффективно, как казалось, и ускорение далеко не столь значительное. Почему так? Ответ виден на схеме: стандартный аллокатор памяти вносит слишком большие накладные расходы.

К блоку, выделенному стандартной функцией malloc, прилагаются размер, ссылка, флаги, грубо говоря, 24 байта «из воздуха». Мало того, сам указатель — это ещё восемь байт. Плюс список, в который объединены эти блоки, тоже далеко не самый эффективный способ организации памяти.

Появился новый класс решений — специфические аллокаторы памяти. Честно говоря, не уверен, что здесь можно говорить о каком-то золотом стандарте. Скорее всего, его нет: область относительно молодая. Но на роль такого стандарта, на мой взгляд, вполне годится MATRAS (Memory Address TRAnSlation) — аллокатор, созданный в компании (тогда ещё) mail.ru и применяемый в таких базах данных, как Tarantool и Picodata.

Есть отличные доклады и статьи на Хабре, где MATRAS описывается подробно. Например:

Если коротко, то идея в том, что дескриптор области памяти — это не указатель, а набор индексов. Один индекс указывает на массив, другой — это индекс в следующем массиве. Получается двойная косвенность. Очевидно, это слабое место, но, как мы обсуждали раньше, у современных процессоров большой кэш, благодаря которому двойная косвенность работает очень быстро. Все остальные эффекты такой конструкции — только положительные:

  • память выделяется массивами с блоками фиксированного размера, а значит, нет внешней фрагментации;

  • массивов много, и блоки в разных массивах могут быть разного размера — это убирает внутреннюю фрагментацию;

  • дескриптор 32-битный, а не 64-битный, экономим ещё немного памяти;

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

В итоге имеем:

  • конкуренции за страницы нет,

  • расход памяти существенно уменьшился,

  • объём журнала минимальный, поскольку тут как раз можно ограничиться записью в журнал только ключей и значений,

  • за счёт версионности возможна обработка гибридной нагрузки.

Кажется, все проблемы решены. Но — увы! — нет. Базы данных в памяти так и не стали мейнстримом. Они заняли свою важную нишу, но традиционные СУБД не вытеснили.

Вы, наверное, скажете: «Это дорого». Только не говорите это разработчикам баз данных в памяти. Они сразу покажут картинку, где за последние 40 лет память подешевела в десятки тысяч раз, а если учесть инфляцию — и вовсе в миллион.

Поэтому, пока речь не идёт о покупке памяти для enterprise-хранилища, можно считать, что она дешёвая. Но это не главная проблема. Куда важнее — эластичность.

Если у вас дисковая база, и вы знаете, что когда-нибудь она вырастет до 100 ТБ, можно спокойно купить 10 ТБ, а потом постепенно добавлять ещё. Более того, транзакции пишутся на диск, и неважно, будет их сегодня больше, завтра меньше — доступ останется одинаковым.

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

Интеллектуальное хранилище

Разработчики и инженеры продолжают искать способы улучшить дисковые базы данных. В 2017 году компания Amazon предложила замечательную идею: а что если система хранения будет не просто «тупым диском», куда можно что-то записать или считать, а интеллектуальным устройством, которое умеет преобразовывать данные?

Так появилась база данных Aurora — по сути, слегка модифицированный MySQL.

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

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

Тем не менее подход оказался весьма эффективным, и у него появилось много последователей. Сегодня у каждого крупного вендора есть база данных, построенная по схожим принципам:

  • Alibaba PolarDB (2017)

  • Microsoft SQL DB Hyperscale / Socrates (2019)

  • Google AlloyDB (2022)

  • Neon (2022)

Отдельно стоит упомянуть китайский PolarDB. Формально заявляется, что он появился в 2017 году — то есть одновременно или даже чуть раньше, чем Aurora. Но у китайских коллег уже были случаи, когда между первой и второй версиями базы данных общего оставалось только название, а архитектура менялась полностью. Так что 2017 год оставим на их совести.

Улучшения внутри Postgres

Есть и другое направление развития традиционных хранилищ. Здесь интересно обратить внимание на проект OrioleDB. Это не самостоятельная база данных, а замена системы хранения для Postgres. Что сделали коллеги:

Замена ссылок на страницы. Полностью отказались от heap tables (неупорядоченных таблиц). Все данные хранятся только в B-деревьях, а страницы дерева связаны между собой ссылками. При загрузке страницы в память просто ссылка на дисковую страницу заменяется ссылкой на образ этой страницы в памяти. Нет поиска адреса по кэшу, есть прямой поиск по ссылкам. Это сильно ускоряет работу и экономит время.

Copy-on-write. Если данные на странице изменяются, то страница записывается на новое место. В итоге нет ненужных версий строк. Общий объём хранилища немного увеличивается, но при нынешней стоимости дисков это не проблема.

Оптимизация структуры страниц. Раньше конкуренция шла за всю страницу. В Oriole данные разделены на фрагменты (chunks), и spin-lock ставится не на всю страницу, а на фрагмент, что резко снижает конкуренцию между параллельными процессами.

Списки undo. Для отката транзакций нужна отдельная область хранения. В Oracle это специальные сегменты, в Postgres — сами страницы с данными. В Oriole для данных отмены сделали специальную область памяти, содержимое которой почти никогда не пишется на диск. Данные приходится сохранять, только если очень длинные транзакции проходят через несколько контрольных точек. В остальных случаях undo живёт в памяти, и объём записи сильно уменьшается.

Логический WAL. Самое важное — отказ от записи физических изменений страниц в журнал. В Oriole используется логический журнал, и его объём сразу уменьшается в 4-5 раз. В нагрузочных тестах это дало кратный рост производительности — в те же 4-5-6 раз. Но именно это и сила проекта, и его слабость: совершенно непонятно, как быть с репликацией данных.

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

При этом сами авторы Oriole не считают это проблемой. Параллельное применение у них используется только при восстановлении после сбоя. В этот момент база недоступна, транзакционная целостность никому не нужна. Важно лишь, чтобы система в итоге пришла в согласованное состояние. А вот при репликации критичны именно промежуточные состояния. Поэтому проект интересный, но, на мой взгляд, не очень жизнеспособный.

Хранилища «ключ-значение» и Titanium

Было бы здорово объединить эти два подхода. Пусть у нас будет отдельная система хранения, но протокол общения с ней будет не страничный, а «ключ—значение».  Такие платформы тоже есть, их много. Например, Titanium.

Здесь есть вычислительный узел и хранилище данных, а между ними — протокол «ключ-значение». На первый взгляд всё выглядит отлично. Но если присмотреться, не всё так просто.

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

В итоге вычислительный узел сам становится узким местом. И решение для масштабирования кажется очевидным: сделать несколько вычислительных узлов.

Но тут появляется новая проблема: мы фактически получаем распределённую базу данных со всеми её сложностями.

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

Распределённые базы данных

Здесь уместен старый анекдот. Новопреставленного программиста апостол Пётр водит по небесному вычислительному центру, показывает суперсовременное оборудование и говорит: «Вот это рай». — «Подожди, а где ад?» — «Ад тоже здесь, но только для администраторов».

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

Представьте корпус корабля, разделённый водонепроницаемыми переборками. При аварии экипаж обязан задраивать переборки, и даже если один отсек затоплен, корабль можно спасти. С монолитной базой то же самое: при сбое всегда чётко очерчена зона поражения. Даже из состояния «сгорело всё, ничего не осталось» восстановление из резервной копии занимает считанные часы.

А вот распределённая база — это потенциально неограниченная зона поражения. Как сказали мне коллеги из Google: «Если Spanner упадёт, завтра вы узнаете об этом из всех газет».

Неопределённый порядок транзакций

Есть ещё один тонкий момент — порядок транзакций. В распределённых системах разные гарантии упорядоченности оперируют изменениями, а не транзакциями. Транзакциями оперирует только высший уровень гарантий — сериализация.

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

Для программиста это может не играть большой роли: независимые изменения и так выполняются независимо. Но когда администратора просят восстановить базу «на точку во времени», начинается креатив в плохом смысле слова. Кажется, что это редкая задача? На практике нет. Коллеги, которые сопровождают базы данных, говорят о сотнях таких запросов в день. Чаще это частичное восстановление, а не полное, но если каждый из сотни запросов превращается в творческий процесс — удовольствие ниже среднего.

Большие задержки

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

Транзакционные vs аналитические нагрузки

Есть ещё одна деталь, о которой я не упомянул, говоря про Titanium. Помимо Key-value хранилища, там есть так называемое Titanium Flash-хранилище. Оно не строчное, а колоночное и предназначено для аналитических запросов.

Если спросить людей, которые работают с базами данных лишь поверхностно, чем аналитическая база отличается от транзакционной, многие ответят, что это именно колоночное хранилище. Это не совсем так.

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

  • Транзакционной базе нужен кэш, потому что она работает с ограниченным набором данных, это скользящее окно. Количество выполняемых запросов небольшое, наверное, сотни. Они простые, но выполняются очень много раз. Я видел статистику, где один запрос исполнялся миллиард раз в сутки. Конечно, есть вопросы к разработчикам, зачем они так написали, но база это выдерживала. В транзакционной СУБД жизненно необходим кэш запросов, чтобы один раз скомпилировать и потом исполнять по дескриптору.

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

Получается, что в транзакционном режиме мы выкручиваем «ручки» одним образом, а в аналитическом — прямо наоборот.

Объединение двух миров

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

С чувством, что я сделал величайшее открытие, я пошёл на зимний HighLoad и попал на доклад коллег из Яндекса про СУБД YTsaurus.

Мало того, что они придумали это намного раньше меня, они ещё реализовали это в железе и в качестве маскота выбрали гибрид слона с ежом :)

У коллег несколько аналитических движков, и ничто не мешает добавить четвёртый, пятый или шестой. Есть и транзакционный движок — динамические таблицы. Причём кэш хранится не только в памяти, но и на флеше. Это позволяет выжать максимум производительности из современного «железа», при этом не слишком заботясь о надёжности: её обеспечивает распределённая система хранения. Если узел отвалится, всегда можно поставить второй такой же, и кэш постепенно прогреется.

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

Другая реальность: как выбирают СУБД

Но если мы спустимся с небес на грешную землю и посмотрим рейтинг db-engines.com, то увидим, что все эти замечательные системы даже не входят в первую сотню. Бал правят самые традиционные СУБД, которым уже больше полувека.

Почему так происходит? Потому что при выборе базы данных критерий «инновационность» практически не играет роли. Главное — это эксплуатационная зрелость. Когда я впервые употребил это слово, думал, что оно понятно всем. Но позже понял, что лучше раскрыть подробнее:

  • Наличие специалистов. Насколько быстро можно расширить или заменить команду.

  • Качество поддержки. Для корпораций — это уровень сервиса от вендора, для open-source — активность сообщества и форумов.

  • Инструментарий. Инструментов должно быть много, они должны быть удобными и разнообразными.

Если мы посмотрим, что именно измеряет рейтинг популярности db-engines, то окажется, что он фактически оценивает всё перечисленное. Получается система с положительной обратной связью: чем платформа популярнее, тем популярнее она становится. Тем не менее тренды могут идти как вверх, так и вниз, и борьба за позиции вполне имеет смысл.

Второй важный критерий — это универсальность.

Хорошо иметь, например, Milvus для векторного поиска или VictoriaMetrics для временных рядов. Но в принципе со всем этим вполне справится один Postgres. Для большинства компаний этого достаточно, можно экономить на поддержке, компетенциях разработчиков и многом другом. Единственные, кому выгоден «зоопарк» решений, — это облачные провайдеры вроде Amazon или, в наших реалиях, Яндекса.

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

Возможно, вы узнали картинку — это 1С. Мы можем дружно посмеяться: где HighLoad, а где 1С? Но зарплату получать любят все, и в этой нише конкурентов у 1С нет — и, думаю, не появится в обозримой перспективе. Поэтому рынок устроен именно так, как он устроен.

Какой должна быть идеальная база данных

Самый главный вопрос: какой должна быть база данных, что такое идеал? Возможно, это провокационный вопрос, но ответ на него, как ни странно, можно найти в русской классике. Агафье Тихоновне, героине гоголевской «Женитьбы», не удалось провернуть свой трюк с женихами, то я всё же надеюсь, что разработчикам баз данных это удастся. И нынешнее поколение если и не будет жить при коммунизме, то хотя бы будет работать с идеальной СУБД.

В порядке небольшой саморекламы: чтобы лучше понять, что такое идеал, выбрать его и, может быть, даже когда-нибудь создать, рекомендую свою книгу «Путеводитель по базам данных»: в бумажной или pdf-версии.

Итоги

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

Инженеры предлагают разные варианты обхода: базы данных в памяти, умные системы хранения (Aurora), альтернативные системы хранения (OrioleDB), протоколы «ключ-значение» (Titanium). Каждый подход снимает часть проблем, но также добавляет свои.

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

И хотя примеры вроде YTsaurus показывают, что объединение разных движков в одной системе вполне возможно, рынок всё же выбирает не «самую инновационную» базу, а зрелую, универсальную и поддерживаемую платформу. Поэтому Oracle, PostgreSQL и Microsoft SQL Server продолжают лидировать.

Идеальная база данных должна объединять скорость транзакций, удобство аналитики, эластичность распределённых систем и эксплуатационную зрелость. Пока такой СУБД нет, но движение в эту сторону уже началось.

Скрытый текст

Уже 6 и 7 ноября HighLoad++ 2025 соберёт инженеров, которые знают, что пределы производительности упираются не в «железо», а в архитектуру. Мы обсудим in-memory базы, умные хранилища, распределённые системы и реальные кейсы построения отказоустойчивых сервисов.

Комментарии (11)


  1. Kisva
    20.10.2025 10:11

    Хорошо бы упомянуть хотя бы в ссылках к Вашей статье книгу - К. Дж. Дейт "Введение в системы баз данных", - для экскурса в историю и понимания, почему БД стали развиваться по такому пути,


    1. hard_sign Автор
      20.10.2025 10:11

      Для понимания очень рекомендую вот эту статью:

      https://habr.com/ru/companies/postgrespro/articles/899380/


  1. smagen
    20.10.2025 10:11

    Большое спасибо, что уделили внимание проекту OrioleDB!

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

    При этом сами авторы Oriole не считают это проблемой. Параллельное применение у них используется только при восстановлении после сбоя. В этот момент база недоступна, транзакционная целостность никому не нужна. Важно лишь, чтобы система в итоге пришла в согласованное состояние. А вот при репликации критичны именно промежуточные состояния. Поэтому проект интересный, но, на мой взгляд, не очень жизнеспособный.

    Вот тут вынужден не согласиться с такими сильными и такими печальными выводами. Репликация у нас работает! Просто видимость считается по минимуму между воркерами. То есть видимы те транзакции, по которым уже все воркеры отработали. Благодаря этому мы видим косистентное состояние.


    1. hard_sign Автор
      20.10.2025 10:11

      Идея понятна, спасибо. Но до чего ж сложная конструкция получается! Для каждой транзакции надо следить не только за тем, что отработали все воркеры, но и за тем, что завершились все предыдущие транзакции. Ну и плюс само понятие «видимости» не так-то просто: это в традиционном PostgreSQL xmin и xmax, а тут приходится следить за тем, какие страницы показывать, какие нет...

      Жесть.

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

      Спасибо за разъяснения!


  1. nin-jin
    20.10.2025 10:11

    И ни слова про объектные субд, графовые, мультимодельные, шифрованные, конвергентные …


    1. hard_sign Автор
      20.10.2025 10:11

      Да и вообще ни слова про модель данных, как так можно! Но вы можете сами подать заявку на HighLoad и рассказать обо всём этом.


      1. nin-jin
        20.10.2025 10:11

        Заявку-то подать, конечно, могу, но есть нюанс.


        1. hard_sign Автор
          20.10.2025 10:11

          Не могу судить, насколько это справедливо. Но я вот так же с улицы пришёл туда, и несколько моих докладов приняли.


          1. nin-jin
            20.10.2025 10:11

            У меня такая же нога и не болит.


  1. akardapolov
    20.10.2025 10:11

    Возьмём, например, Oracle, который может очень эффективно работать и в качестве транзакционной базы, и в качестве аналитической, но только в одном режиме одновременно:

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

    Но лучше настроить. Надо разделить OLTP и DSS нагрузку - транзанкционные данные кладем в отчетные таблицы для чтения, закрепляем из в RECYCLE пуле буферного кэша (они не будут болтаться там в DEFAULT пуле с транзакционными таблицами + меньше конкуренция за блоки в буферном кэше + исключение ошибок ORA-01555 Snapshot Too Old + можно поставить раза в 2-3 больше размер блока данных, для них тоже есть спец. пулы в буферном кэше - тоже ускорит выполнение запросов). Отчетные таблицы - в INMERORY пул, там Oracle в поколоночном виде будет обрабатывать данные для пользователей, создающим DSS нагрузку. Ну и отдать автоматике управление памяти SGA + PGA - MEMORY_TARGET.

    Если мощи сервера не будет хватать - можно добавить ACTIVE STANDBY - backup из коробки на горячую + DSS пользователей туда перенаправить.


    1. hard_sign Автор
      20.10.2025 10:11

      Вы правы, можно. Особенно, конечно, в этом плане полезно наличие нескольких буферных пулов — в Oracle их аж 6 штук вроде как можно сделать. Но если это разнести на два экземпляра на двух разных машинах, будет лучше со всех точек зрения.