Это коллективный пост от трёх рыл сразу. Есть примитивная самописная на C++ СУБД. Некая не сложная софтина, внутри имеющая самописное B+-Tree или даже не B+-Tree, а что-то ещё более тупое и простое, но умеющее в сравнимый по эффективности доступ к части данных на диске. Реализована семантика таблиц. Таблица - это последовательность строк. Строка - это последовательность строго типизированных полей (колонок). Строка - это кортеж. Строки лежат отсортировано в порядке Primary Key. PK - это конкатенация (суб-кортеж) каких-то колонок, по которой (суб-кортежу) сортируются строки (ну в общем тут всё как везде, как в mysql внутри). Физически строка - это тупо конкатенация всех колонок. Например при схеме (id : int32, age : int32, time : int32) строка будет представлять собой три четырёхбайтных поля и занимать 3*4 байта. Со строками переменной длины может чуть сложнее, но вы поняли. Ну и ещё у таблички хранится схема (один раз), чтобы понимать, где в этих 12 байтах искать поле time (отступи 8 байт и вот оно).
Код очень тупой и там не особо много строк. Он настолько тупой, что нет реляционности и она не нужна - ну то есть база не понимает отношений между таблиц, форин кеев и джоинов. Таблица - это тупо «неймспейс со схемой», в который можно навалить строк. Таблица - это как каталог, куда можно напихать строк согласно схеме этой таблицы. Всё это - буквально key=value хранилка, где каждое key=value - это строка таблицы, а в качестве key рассматривается PK этой строки. Ну, логически оно и внутри MySQL такое, только MySQL умеет транзакции, ACID, реляции и всё такое, а здесь ничего этого нет. Есть какие-то простые гарантии, типа что таблица всегда в каком-то целостном состоянии. Но гарантии того, что ты прочитаешь то, что записал до этого - нет, потому что перед твоей операцией чтения кто-то другой мог зайти и насрать. Транзакций-то нет. Ну ладно, не суть. Они и не нужны. Задача только в том, чтобы пользователь видел семантику таблиц, потому что таблицы всем удобны наличием схемы и строго типизированые строки удобны потому, что есть семантика полей и типов этих полей. А, ну ещё оно умеет add column, drop column, alter column - ну бывает захотелось поле добавить или тип поменять. А, ну ещё оно умеет несколько индексов на таблицу - то есть PK может быть один, а ещё 5 индексов других типов по другим под-кортежам - это всё тоже не очень сложно и не очень интересно - каждый индекс - это просто ещё одна какая-то поисковая-индексирующая структура данных сбоку от таблицы.
Ко всему этому прикручен WAL и чекпоинты. В общем, данные не просираются - все пишущие запросы дописываются в конце файлика (который рубится на куски по 512 МБ) - (это наш WAL), и периодически делаются чекпоинты - примерно как в терминологии постгреса, но чуть проще.
Данный код работает максимально близко по производительности к какому-нибудь redis или memcache, потому что он жесть какой тупой (ни транзакций, нихрена). Максимум умного что там происходит - это выпаршивание отдельных полей из пачки байтиков по имени этих полей - то есть не тупое key=value, а умное key=value, которое понимает стурктуру value. Иногда и не понимает - есть тупые запросы типа get_all(), которые не думая отдают в сеть всю строку без её парсинга и валидации. Ну и ещё иногда происходит доступ к диску для подгрузки каких-то страниц, которых в памяти не оказалось - вот это наверное максимально умное. Даже планировщика запросов нет - в языке запросов надо явно указать каким индексом пользоваться при селектах, само не догадается. Таким образом, индексы - это как-бы отдельные структуры данных, которые смотрят в ту же таблицу и которые явно указывает юзер. Очень тупо, да, зато надёжно как кусок кирпича.
Тянет один такой процесс на сервере сейчас 20K RPS любых типов (чтение или запись) в один поток (если данные в памяти конечно есть и на долгий диск не пришлось ходить). Надо больше - горизонтально масштабируем и готово (ну да, чтобы посчитать число строк, в которых time > 123 AND time < 888, придётся послать запрос на все процессы и проагрегировать на запросчике, но это редко нужно). Опять же не суть, рассматриваем один процесс.
Тут приходит Петрович и говорит - поцоны, вы грибов хапнули, зачем вы всё это пишете на С++ с нуля? Можно же просто взять SQLite, залинковать со своим сетевым интерфейсом и DBMS готова! И думать не надо и всё оттестировано сотнями миллиардов леммингов и быстро работает - применяемость sqlite на самых слабых смартфонов для хранения конфигов и куки соврать не дадут.
Вопрос - где будут просадки по производительности или по какому-то другому важному параметру, например по поддерживаемости и изменяемости кода?
Вот например, сейчас в нашем простом коде мы имеем то преимущество, что он туп и его не много. Можем легко допиливать кастомные фичи под конкретных клиентов - например иногда клиент хочет, чтобы каждые 100 новых строк в его таблице ловко агрегировались и вставлялись в другую таблицу, в которой лежало бы только 2000 последних строк, а старые самоудалялись без тормозов. Ну и всё такое. То есть, первый пункт - простота и модифицируемость под свои нужды.
Второй пункт, вытекает из первого. Хоть в SQLite багов и нет, но применяя SQLite мы уже не умеем отвечать на вопрос «почему тормозило». Надо инвестировать полгода-год в чтение исходников SQLite фуллтайм и в становление SQLite-хакером. Сходу мы становимся рабами готовой библиотеки, про которую можем отвечать только «да хрен его знает почему не больше 4К запросов в секунду, день такой!».
Далее, какие-то приколы с SQLite, о которых мы не знаем - например какие-то неожиданные блокировки таблиц при каких-то операциях и прочая сложность, ввиду наличия транзакций или особенностей архитектуры - тут требуется помощь зала.
В общем, я сказал что хотел, послушаем мнения из зала! Просьба говна не писать, мамку не упоминать и троллингом не заниматься - оскорбления и наезды нас не растрогают - скорее всего вы будете достаточно слабы, чтобы пробить нашу челябинскую душу, и на ответку не спровоцирует, а тролление нам скучно, ибо мы сами троли 80 левела со стажем, сами кого хош гопстопнем и затроллим и за жизнь обоснуем, но в специально отведённых местах, а здесь это не интересно и нужен конструктив (даже если он очевиден и банален). Тролленх и говно будем игнорить, призываю к конструктиву в треде! Если кажется, что автор мудак и не понимает банальных вещей, то так и есть - иначе бы он на вопросы отвечал, а не задавал их. Если кажется, что с мудаками общаться бесполезно, то и не общайтесь, будет супер. Спасибо!