Загрузил в феврале 2021-го 150 гигабайтных файлов (.partXX.rar), проверил через полтора-два года. Одного файла нет, на нескольких один-два байта в середине файла изменены. Было бы первый раз - подумал бы глюк какой-то, но подозрения уже были раньше. Так что сравнил с другим бэкапом.
Живу в США, участвовал в class action по утечке данных Equifax. Обещали "до $125 налом". Заполнил на себя и на жену. Спустя пару лет после того, как я присоединился к иску, прислали мелкий вопрос. Ответил (только за себя). В декабре 2022-го наконец-то прислали чек, только мне. Сумма в чеке $5.21 (прописью - пять долларов).
Для каждой позиции хранится не только результат Выигрыш/Ничья/Проигрыш (что можно упаковать 5 в один байт), но и то как в ней ходить. Ведь если в дамочном окончании выигрыш где-то очень далеко, то просчет не добивает, а знание результата не позволяет достичь выигрыша без просчета/перебора.
Отвечая на ваш вопрос, порядок полей скорее всего не имеет значения. Важно то, что "соседние позиции" повторяют результат. Хорошо, если соседние поля имеют близкий индекс - это позволяет усилить сжатие, но например в окончаниях важно владение большаком (диагональю a1-h8), а кодировать такие аспекты - вряд ли эффективно.
Есть довольно простой способ сравнения. Сравнить скорость генерации ходов. С представлением 12 байт на позицию (3 маски по 32 бита) мой генератор ходов выдавал 10 миллионов генераций в секунду (когда частота процессоров была 2-3 ГГц; само собой - на одно ядро). Ваш генератор (посмотрел в исходники) способен на сотни тысяч в секунду, не больше.
Достаточно 3 битовых масок, где каждая - 32 бита (количество полей). Одна маска - белые фигуры, вторая маска - черные фигуры, третья маска - дамки. Это самое эффективное представление.
Если вдруг интересно использовать наработки эндшпильной базы от Тундры, обращайтесь в личку. Параметры сжатия такие: в 4ГБ хранится 400 млрд позиций.
Идея США заключается в том, что штаты конкурируют между собой за людей, а люди выбирают штат, который они считают наиболее им подходит. Так было задумано при основании США. К сожалению, это начало меняться с появлением федерального налога на доходы, немногим более 100 лет назад. Соответственно, все идет к тому, что налоги будут устанавливаться из центра (чем дальше, тем больше), и все менее важен становится выбор каждого жителя.
Проблемы бывают в неожиданных местах. Например, с русским языком.
Символы ё и й могут быть представлены по-разному. Один вариант - это кодирование символа одним код-поинтом, второй вариант - двумя (первый базовая буква е/и, второй - модификация).
При этом, на системах от Apple используется второй вариант, а на Windows - первый. Но обе системы отображают оба варианта. Разница заметна только если копаться в байтовых представлениях (или например Far Manager не в курсе про второй вариант, показывает разорванные буквы иногда).
Теперь про сравнение строк. Есть несколько уровней сравнения: первый - accent insensitive, второй - case insensitive. В режиме сравнения без учета акцента буквы е и ё, а также и и й считаются одинаковыми. Поэтому с точки зрения механизмов сортировки довольно удобно сделать так, как делает Apple, как раз из-за наличия режима accent insensitive.
Сравнение строк. Есть равно/неравно, а есть больше/меньше. Со вторым куда больше проблем. Например, русский алфавит заканчивается: Ы Ь Э Ю Я. Украинский алфавит заканчивается: Ш Щ Ю Я Ь. Код-поинты одинаковые. Не существует порядка, удовлетворяющего двум языкам. Поэтому для сортировки нужно знать язык сортировки (локаль).
По большому счету, у вас самые большие оптимизации выполнены.
Основная цель оптимизации алгоритма перебора - это увеличение количества отсечений. То есть лучше не делать работу по перебору позиций, если вся ветка будет впоследствии отсечена другим ходом. Можно еще чуть дожать отсечения, если использовать NegaScout алгоритм (вариация альфа-беты, но симметричная). Я еще пробовал MTD(f), но каких-то существенных улучшений от использования алгоритма не заметил.
Что у вас не хватает - это отсечения по границам. Например, в переборе на определенную глубину вы нашли, что позиция оценена как 200. Если эта оценка между альфой и бетой, то вы сохраняете в хэш точную оценку позиции. Потом ее прочитаете - и используете, здесь все правильно. Но если вы нашли оценку 200, когда ваша альфа 200, то у вас отсечение, а не оценка позиции. В будущем - иногда вы можете отсечь (если следующий перебор будет с более режущими условиями), а иногда - нет.
Вам тут в соседних комментариях указывают на то, что списком хранить хэш-таблицу не стоит, а стоит использовать что-то более оптимальное. Также стоит обратить внимание на представление доски. Использование битовых масок, если на доске нет дамок, позволяет определить наличие возможности боя (бой обязателен) без перебора каждой шашки. Скорость генератора ходов на частоте процессора 2ГГц была около 10 млн генераций/сек. Это на одном ядре, конечно же.
Оценочная функция - это основное в шашечной программе (имхо), если все оптимизации сделаны. У вас ее уровень - слабый. Учитывание материальных факторов (стремление к материальному перевесу) - это база игры в шашки, но оценка позиции должна быть намного более комплексной. Здесь остро проявляется отличие шахмат от шашек: в шахматах фигуры разные, а в шашках - одинаковые. Это делает игру интереснее и сложнее в плане оценки позиции. В подавляющем большинстве случаев дамки появляются либо только у одной из сторон, либо в эндшпилях (кол-во фигур менее 10). Если дамка появляется в середине партии, да еще и у каждой из играющих сторон, то такие позиции оценить крайне тяжело. Но таких партий очень мало.
Перспективные направления в шашечном программировании я бы назвал такие: миттельшпильные базы (хранение возможности выигрыша в позиции, которая не расчитана в ЭБ), нейронные сети по построению оценочной функции, и использование параллельных алгоритмов (альфа-бета очень плохо параллелится). Конкуренты (другие программы по игре в шашки) ведут расчет глубже за счет еще больших отсечений. Я не знаю как к этому относится, на тот момент когда это стало актуально, я уже отошел от программирования шашек.
В шашках ничейная смерть у турниров начала просматриваться довольно давно. С появлением компьютерных программ - проблема стала намного острее. В частности, игра по переписке почти умерла из-за этого.
В итоге - некоторые турниры проводятся с жеребьевкой 1-2 первых ходов, некоторые из модифицированной стартовой позиции (летающая шашка). Результатом в таких турнирах является результат микро-матча, когда игроки поочередно играют одну и ту же стартовую позицию сначала белыми, а затем черными. Вероятно, только блиц-турниры (5 мин на партию) из начальной позиции еще дают какие-то результаты.
Насчет правил - когда я читал было написано про большинство. Вы исправили в статье или я ошибся?
Тундра - программа для игры и анализа шашечных позиций (и партий). Последняя версия 2.4.6, вышла в феврале 2006. Первая версия (не публичная) была - в 2002м. Последняя демо-версия была 2.4.5, в ней был таймер на 10 минут (после этого программа завершала работу). Демо играла хуже, чем проф. версия, которая продавалась до 2009-го примерно.
Найти демо-версию, вероятно, можно на торрентах, и скорее всего с отломанным таймером. Размер исполняемого файла - в районе 300кБ. Обычно вирусы весят больше, так что если размер сильно больше - остерегайтесь. Официальный сайт - в дауне последние несколько лет. Но интернет многое помнит :)
У вас в правилах ошибка. В русских шашках нет обязанности бить большинство. Это правило из международных шашек (поле 10 на 10, "стоклетки"). Другое отличие стоклеток от русских - это правило боя через дамочное поле (в русских шашка становится дамкой и продолжает бой как дамка; в стоклетках бой продолжается как шашка если возможен). Если применить правила стоклеток на малую доску (8 на 8), то получатся бразильские шашки.
Есть еще такая тема, как эндшпильные базы. Для количества фигур меньше определенного можно расчитать все позиции. В Тундре (шашечная программа, я - один из авторов) полная сжатая 8-фигурка была около 5ГБ (это половина базы, которой достаточно программе для получения результата позиции мгновенно). Было развитие темы в сторону неполных эндшпильных баз, но перспективы этого направления ждут очередного исследователя. В вашей статье рассматривается дебютная библиотека, а не эндшпильная. В эндшпильных базах не хранится позиция, там строится индекс позиции, а в базе хранятся только значения В/Н/П (или количество ходов до выигрыша/проигрыша или перехода в следующий подкласс ЭБ).
PS. Еще кажется, что у вас алгоритм боя неправильно закодирован. Навскидку, он должен быть сложнее. Например, в позиции б.д. a1, ч.ш. b2 доступно 6 ходов (бой с a1 на c3, d4, e5, f6, g7, h8). Если добавить черную на f4, то должно быть 2 хода (a1:e5:g3; a1:e5:h2).
При дизайне СУБД с использованием SCN, каждое изменение имеет ссылку на прошлую версию той же записи. Таким образом, если вторая транзакция читает обновленные данные, но знает что ей нужны более старые (см. выше про необходимость знания транзакцией своего стартового SCN), то она по ссылкам в записи проходит дальше в историю, чтобы получить данные на тот момент, когда ей необходимо. Вопрос сколько истории хранить - регулируется размером UNDO TABLESPACE в Oracle. Возможны ошибки, что "транзакция слишком длинная, истории не хватило" - тогда есть 2 выхода: либо увеличить объем UNDO (область админа), либо изменить логику приложения (область разработчика).
СУБД общего назначения не может расчитывать ни на то, что вся таблица поместится в RAM, ни на то, что все изменения одной транзакции поместятся в RAM. Это слишком опрометчиво с точки зрения дизайна, и на практике рано или поздно случится так, что это ограничение будет нарушено.
Помимо механизмов изоляции транзакций, СУБД еще должна заботиться о резервном копировании (и репликации на другие инстансы, если смотреть еще дальше). Здесь тоже встают вопросы как минимизировать объем данных в резервной копии (или объем передаваемых данных на реплику).
Мораль здесь такая: для разработки своей СУБД лучше изучить существующие решения и выбрать работающие решения (отказавшись от ненужных фич), а не пытаться решить проблемы по мере их поступления. Последний путь - дороже в общем случае.
Ответ на ваш вопрос в последнем абзаце (отсылка к книге как устроен Oracle внутри).
У вас сейчас табличные блокировки. Любой изменяющий должен выставить блокировку на таблицу, и от момента блокирования таблицы до момента коммита транзакции таблица недоступна (для других). В стандарте SQL92 вопрос проработан дальше - блокировка ставится на запись, а не на таблицу, но ожидания все равно остаются.
В Oracle ключевым понятием является SCN. Это единый, сквозной номер изменения в БД. Любое изменяющее действие увеличивает этот номер (чтение может не увеличивать). Но каждая транзакция помнит "свой" стартовый SCN, от которого она должна отсчитывать все изменения.
То есть чтобы прочитать данные нужно не только знать что читать, но и то, на какой момент это читать.
Соответственно, изменения в любую запись БД вносятся с учетом этого SCN. Более подробно - вам лучше все же книгу почитать. Поверьте, это пока что поверхностный уровень. Внутри куда все сложнее, особенно с блокированием при изменении индексов.
SQLite является файловой СУБД. К файлу БД можно обращаться по сети. Если ваша цель реализация СУБД на основе файлов, то не забудьте обеспечить возможность такого обращения, желательно с хоть каким-то уровнем блокировок, то есть чтобы не блокировалась вся БД при обращении кого-то одного.
Есть такая СУБД, называется Oracle Database. Славится тем, что не следует (не следовала) стандартам. Например, пустая строка и NULL в понимании этой СУБД - это одно и то же.
Так вот, ее основное достоинство (имхо) - это версионность записей в БД. Рассмотрим пример: транзакция Т1 меняет запись, и дальше что-то делает. Транзакция Т2 пытается читать измененную запись. По стандарту SQL92 вторая транзакция должна встать в ожидание (на всех уровнях изоляции выше read uncommitted). Но с Oracle ситуация другая: на этой СУБД вы получите прошлую версию записи сразу, без блокировки.
Получается, что целостность (consistency) приобретает другой смысл. Оказывается важно, чтобы все чтения транзакции Т2 были сделаны из одного и того же среза (snapshot) данных. И этот срез фиксируется началом транзакции.
Собственно, на заре нулевых, когда NoSQL еще не было, а споры что лучше MSSQL или Oracle были, основным достоинством последней было именно наличие другой модели блокировок и работы с данными.
Вы здесь упоминаете SQL92, но Oracle как мне кажется, добивался большей параллельности (и следовательно большей производительности) не за счет выполнения стандарта, а за счет решения задач более высокого уровня. У MSSQL было лучше с реализацией, но у Oracle было лучше с концепцией.
Если вы реально интересуетесь темой, то я бы порекомендовал прочитать книгу Oracle Core (автор - Jonathan Lewis). Из книги вы узнаете, например, почему у блоков, хранящих данные таблицы, всего 1 слот для блокировок, а у блоков с данными индексов 2.
Есть еще вариант использовать GraalVM - это машина, которая компилирует java class файлы в машинный код, попутно откусывая все ненужное. В итоге - hello world приложение сокращено до 1.5МБ.
Укажите что у гостя 2 ядра.
Ага и порчу файлы я сам по вашей же логике.
Загрузил в феврале 2021-го 150 гигабайтных файлов (.partXX.rar), проверил через полтора-два года. Одного файла нет, на нескольких один-два байта в середине файла изменены. Было бы первый раз - подумал бы глюк какой-то, но подозрения уже были раньше. Так что сравнил с другим бэкапом.
Поосторожнее с OneDrive. Я отказался от него после того как поймал за руку на 1) удалении файлов; 2) порче файлов.
Мой прогноз что и по $8 не получат.
Живу в США, участвовал в class action по утечке данных Equifax. Обещали "до $125 налом". Заполнил на себя и на жену. Спустя пару лет после того, как я присоединился к иску, прислали мелкий вопрос. Ответил (только за себя). В декабре 2022-го наконец-то прислали чек, только мне. Сумма в чеке $5.21 (прописью - пять долларов).
Можно параллельно проверять все шашки. Например, a1, c1, e1 могут бить, если на b2, d2, f2 стоит черная фигура и поле c3, e3, g3 - пустое.
Для каждой позиции хранится не только результат Выигрыш/Ничья/Проигрыш (что можно упаковать 5 в один байт), но и то как в ней ходить. Ведь если в дамочном окончании выигрыш где-то очень далеко, то просчет не добивает, а знание результата не позволяет достичь выигрыша без просчета/перебора.
Отвечая на ваш вопрос, порядок полей скорее всего не имеет значения. Важно то, что "соседние позиции" повторяют результат. Хорошо, если соседние поля имеют близкий индекс - это позволяет усилить сжатие, но например в окончаниях важно владение большаком (диагональю a1-h8), а кодировать такие аспекты - вряд ли эффективно.
Есть довольно простой способ сравнения. Сравнить скорость генерации ходов. С представлением 12 байт на позицию (3 маски по 32 бита) мой генератор ходов выдавал 10 миллионов генераций в секунду (когда частота процессоров была 2-3 ГГц; само собой - на одно ядро). Ваш генератор (посмотрел в исходники) способен на сотни тысяч в секунду, не больше.
Достаточно 3 битовых масок, где каждая - 32 бита (количество полей). Одна маска - белые фигуры, вторая маска - черные фигуры, третья маска - дамки. Это самое эффективное представление.
Если вдруг интересно использовать наработки эндшпильной базы от Тундры, обращайтесь в личку. Параметры сжатия такие: в 4ГБ хранится 400 млрд позиций.
Идея США заключается в том, что штаты конкурируют между собой за людей, а люди выбирают штат, который они считают наиболее им подходит. Так было задумано при основании США. К сожалению, это начало меняться с появлением федерального налога на доходы, немногим более 100 лет назад. Соответственно, все идет к тому, что налоги будут устанавливаться из центра (чем дальше, тем больше), и все менее важен становится выбор каждого жителя.
Проблемы бывают в неожиданных местах. Например, с русским языком.
Символы ё и й могут быть представлены по-разному. Один вариант - это кодирование символа одним код-поинтом, второй вариант - двумя (первый базовая буква е/и, второй - модификация).
При этом, на системах от Apple используется второй вариант, а на Windows - первый. Но обе системы отображают оба варианта. Разница заметна только если копаться в байтовых представлениях (или например Far Manager не в курсе про второй вариант, показывает разорванные буквы иногда).
Теперь про сравнение строк. Есть несколько уровней сравнения: первый - accent insensitive, второй - case insensitive. В режиме сравнения без учета акцента буквы е и ё, а также и и й считаются одинаковыми. Поэтому с точки зрения механизмов сортировки довольно удобно сделать так, как делает Apple, как раз из-за наличия режима accent insensitive.
Сравнение строк. Есть равно/неравно, а есть больше/меньше. Со вторым куда больше проблем. Например, русский алфавит заканчивается: Ы Ь Э Ю Я. Украинский алфавит заканчивается: Ш Щ Ю Я Ь. Код-поинты одинаковые. Не существует порядка, удовлетворяющего двум языкам. Поэтому для сортировки нужно знать язык сортировки (локаль).
По большому счету, у вас самые большие оптимизации выполнены.
Основная цель оптимизации алгоритма перебора - это увеличение количества отсечений.
То есть лучше не делать работу по перебору позиций, если вся ветка будет впоследствии отсечена другим ходом.
Можно еще чуть дожать отсечения, если использовать NegaScout алгоритм (вариация альфа-беты, но симметричная).
Я еще пробовал MTD(f), но каких-то существенных улучшений от использования алгоритма не заметил.
Что у вас не хватает - это отсечения по границам. Например, в переборе на определенную глубину вы нашли, что позиция оценена как 200.
Если эта оценка между альфой и бетой, то вы сохраняете в хэш точную оценку позиции. Потом ее прочитаете - и используете, здесь все правильно.
Но если вы нашли оценку 200, когда ваша альфа 200, то у вас отсечение, а не оценка позиции. В будущем - иногда вы можете отсечь (если следующий перебор будет с более режущими условиями), а иногда - нет.
Вам тут в соседних комментариях указывают на то, что списком хранить хэш-таблицу не стоит, а стоит использовать что-то более оптимальное.
Также стоит обратить внимание на представление доски. Использование битовых масок, если на доске нет дамок, позволяет определить наличие возможности боя (бой обязателен) без перебора каждой шашки. Скорость генератора ходов на частоте процессора 2ГГц была около 10 млн генераций/сек. Это на одном ядре, конечно же.
Оценочная функция - это основное в шашечной программе (имхо), если все оптимизации сделаны. У вас ее уровень - слабый. Учитывание материальных факторов (стремление к материальному перевесу) - это база игры в шашки, но оценка позиции должна быть намного более комплексной. Здесь остро проявляется отличие шахмат от шашек: в шахматах фигуры разные, а в шашках - одинаковые. Это делает игру интереснее и сложнее в плане оценки позиции.
В подавляющем большинстве случаев дамки появляются либо только у одной из сторон, либо в эндшпилях (кол-во фигур менее 10). Если дамка появляется в середине партии, да еще и у каждой из играющих сторон, то такие позиции оценить крайне тяжело. Но таких партий очень мало.
Перспективные направления в шашечном программировании я бы назвал такие: миттельшпильные базы (хранение возможности выигрыша в позиции, которая не расчитана в ЭБ), нейронные сети по построению оценочной функции, и использование параллельных алгоритмов (альфа-бета очень плохо параллелится). Конкуренты (другие программы по игре в шашки) ведут расчет глубже за счет еще больших отсечений. Я не знаю как к этому относится, на тот момент когда это стало актуально, я уже отошел от программирования шашек.
В шашках ничейная смерть у турниров начала просматриваться довольно давно. С появлением компьютерных программ - проблема стала намного острее. В частности, игра по переписке почти умерла из-за этого.
В итоге - некоторые турниры проводятся с жеребьевкой 1-2 первых ходов, некоторые из модифицированной стартовой позиции (летающая шашка). Результатом в таких турнирах является результат микро-матча, когда игроки поочередно играют одну и ту же стартовую позицию сначала белыми, а затем черными. Вероятно, только блиц-турниры (5 мин на партию) из начальной позиции еще дают какие-то результаты.
http://www.shashki.com/PNphpBB2-viewtopic-t-165.html
Насчет правил - когда я читал было написано про большинство. Вы исправили в статье или я ошибся?
Тундра - программа для игры и анализа шашечных позиций (и партий). Последняя версия 2.4.6, вышла в феврале 2006. Первая версия (не публичная) была - в 2002м. Последняя демо-версия была 2.4.5, в ней был таймер на 10 минут (после этого программа завершала работу). Демо играла хуже, чем проф. версия, которая продавалась до 2009-го примерно.
Найти демо-версию, вероятно, можно на торрентах, и скорее всего с отломанным таймером. Размер исполняемого файла - в районе 300кБ. Обычно вирусы весят больше, так что если размер сильно больше - остерегайтесь. Официальный сайт - в дауне последние несколько лет. Но интернет многое помнит :)
У вас в правилах ошибка. В русских шашках нет обязанности бить большинство. Это правило из международных шашек (поле 10 на 10, "стоклетки"). Другое отличие стоклеток от русских - это правило боя через дамочное поле (в русских шашка становится дамкой и продолжает бой как дамка; в стоклетках бой продолжается как шашка если возможен). Если применить правила стоклеток на малую доску (8 на 8), то получатся бразильские шашки.
Есть еще такая тема, как эндшпильные базы. Для количества фигур меньше определенного можно расчитать все позиции. В Тундре (шашечная программа, я - один из авторов) полная сжатая 8-фигурка была около 5ГБ (это половина базы, которой достаточно программе для получения результата позиции мгновенно). Было развитие темы в сторону неполных эндшпильных баз, но перспективы этого направления ждут очередного исследователя. В вашей статье рассматривается дебютная библиотека, а не эндшпильная. В эндшпильных базах не хранится позиция, там строится индекс позиции, а в базе хранятся только значения В/Н/П (или количество ходов до выигрыша/проигрыша или перехода в следующий подкласс ЭБ).
PS. Еще кажется, что у вас алгоритм боя неправильно закодирован. Навскидку, он должен быть сложнее. Например, в позиции б.д. a1, ч.ш. b2 доступно 6 ходов (бой с a1 на c3, d4, e5, f6, g7, h8). Если добавить черную на f4, то должно быть 2 хода (a1:e5:g3; a1:e5:h2).
При дизайне СУБД с использованием SCN, каждое изменение имеет ссылку на прошлую версию той же записи. Таким образом, если вторая транзакция читает обновленные данные, но знает что ей нужны более старые (см. выше про необходимость знания транзакцией своего стартового SCN), то она по ссылкам в записи проходит дальше в историю, чтобы получить данные на тот момент, когда ей необходимо. Вопрос сколько истории хранить - регулируется размером UNDO TABLESPACE в Oracle. Возможны ошибки, что "транзакция слишком длинная, истории не хватило" - тогда есть 2 выхода: либо увеличить объем UNDO (область админа), либо изменить логику приложения (область разработчика).
СУБД общего назначения не может расчитывать ни на то, что вся таблица поместится в RAM, ни на то, что все изменения одной транзакции поместятся в RAM. Это слишком опрометчиво с точки зрения дизайна, и на практике рано или поздно случится так, что это ограничение будет нарушено.
Помимо механизмов изоляции транзакций, СУБД еще должна заботиться о резервном копировании (и репликации на другие инстансы, если смотреть еще дальше). Здесь тоже встают вопросы как минимизировать объем данных в резервной копии (или объем передаваемых данных на реплику).
Мораль здесь такая: для разработки своей СУБД лучше изучить существующие решения и выбрать работающие решения (отказавшись от ненужных фич), а не пытаться решить проблемы по мере их поступления. Последний путь - дороже в общем случае.
Ответ на ваш вопрос в последнем абзаце (отсылка к книге как устроен Oracle внутри).
У вас сейчас табличные блокировки. Любой изменяющий должен выставить блокировку на таблицу, и от момента блокирования таблицы до момента коммита транзакции таблица недоступна (для других). В стандарте SQL92 вопрос проработан дальше - блокировка ставится на запись, а не на таблицу, но ожидания все равно остаются.
В Oracle ключевым понятием является SCN. Это единый, сквозной номер изменения в БД. Любое изменяющее действие увеличивает этот номер (чтение может не увеличивать). Но каждая транзакция помнит "свой" стартовый SCN, от которого она должна отсчитывать все изменения.
То есть чтобы прочитать данные нужно не только знать что читать, но и то, на какой момент это читать.
Соответственно, изменения в любую запись БД вносятся с учетом этого SCN. Более подробно - вам лучше все же книгу почитать. Поверьте, это пока что поверхностный уровень. Внутри куда все сложнее, особенно с блокированием при изменении индексов.
SQLite является файловой СУБД. К файлу БД можно обращаться по сети. Если ваша цель реализация СУБД на основе файлов, то не забудьте обеспечить возможность такого обращения, желательно с хоть каким-то уровнем блокировок, то есть чтобы не блокировалась вся БД при обращении кого-то одного.
Есть такая СУБД, называется Oracle Database. Славится тем, что не следует (не следовала) стандартам. Например, пустая строка и NULL в понимании этой СУБД - это одно и то же.
Так вот, ее основное достоинство (имхо) - это версионность записей в БД. Рассмотрим пример: транзакция Т1 меняет запись, и дальше что-то делает. Транзакция Т2 пытается читать измененную запись. По стандарту SQL92 вторая транзакция должна встать в ожидание (на всех уровнях изоляции выше read uncommitted). Но с Oracle ситуация другая: на этой СУБД вы получите прошлую версию записи сразу, без блокировки.
Получается, что целостность (consistency) приобретает другой смысл. Оказывается важно, чтобы все чтения транзакции Т2 были сделаны из одного и того же среза (snapshot) данных. И этот срез фиксируется началом транзакции.
Собственно, на заре нулевых, когда NoSQL еще не было, а споры что лучше MSSQL или Oracle были, основным достоинством последней было именно наличие другой модели блокировок и работы с данными.
Вы здесь упоминаете SQL92, но Oracle как мне кажется, добивался большей параллельности (и следовательно большей производительности) не за счет выполнения стандарта, а за счет решения задач более высокого уровня. У MSSQL было лучше с реализацией, но у Oracle было лучше с концепцией.
Если вы реально интересуетесь темой, то я бы порекомендовал прочитать книгу Oracle Core (автор - Jonathan Lewis). Из книги вы узнаете, например, почему у блоков, хранящих данные таблицы, всего 1 слот для блокировок, а у блоков с данными индексов 2.
Как жаль что презентуюзий не знал об этом и показал вывод команды ldd в видео.
Есть еще вариант использовать GraalVM - это машина, которая компилирует java class файлы в машинный код, попутно откусывая все ненужное. В итоге - hello world приложение сокращено до 1.5МБ.
https://www.youtube.com/watch?v=6wYrAtngIVo