Pull to refresh
19
0
Send message

А что касается вопросов:

  • Small alloc и кортержи - не понял вопроса. Кортеж - это единица хранения данных, что-то типа одного ряда таблицы. Хранится в памяти он одним кусоком. Кортежи переменного размера, поэтому для них нужен аллоктор общего назначения. Подошел бы malloc, но вместо него мы используем свой small_alloc.

  • В Тарантуле действительно один транзакционный поток, но есть еще несколько вспомогательных потоков. В частности recovery checkpoint (он же snapshot на диске) пишется из треда. Еще один пример relay поток реплики. Когда приходит пустая реплика и присоединяется к кластеру, для неё создается персональный поток, а чтобы заполнить реплику текущими данными - в этот поток также передается read view всех данных.

  • Про читателя и старые данные - все верно, это и нужно. Читатель дожен получить консистентный неизменный read view на какой-то момент времени, писатель будет создавать новое состояние базы данных, а читатель - получается будет работать с неизменным старым.

Спасибо, поправил опечатки! Кроме:

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

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

Целью статьи было поделиться пониманием MVCC в общем и общими же подходами в реализации MVCC. В частности некоторые вышеописанные подходы вообще не реализованы в Тарантуле. Но понятно, что работа в Тарантул делает мой опыт в той или иной степени однобоким, но что поделать - профдеформация.

Да, первичный ключ — тоже LSM tree. Описание работы винила, имхо, заслуживает отдельной статьи. Но если в двух словах — во время compaction транзакции используют старые файлы. А в момент переключения со старых файлов на новые все итераторы хитрым образом перепозиционируются на новые файлы. Ленивым образом, то есть только при продолжении итерирования, конечно.
Тарантул по-умолчанию — БД в памяти (я упомянул об этом во первых строках этой статьи). Если под «локальный кэш» имеется ввиду кэш файловой системы — то он, соответственно, применим при чтении только к дисковому движку, и там быстродействие чтения упирается в диск нормальным образом. Если же речь про кэш процессора, то объем данных подбирается таким образом, чтобы в кэш он гарантированно не влезал.

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

Как правило речь про рабочий десктоп и 1 миллион записей в базе (если я правильно понял про «размер данных»). Понятно, что десктоп десктопу рознь, боевые сервера слегка другие, а многие вообще на ноутах работают. Но это, как я пишу, грубая оценка, для ответа на вопросы типа «могу ли я ради новой фичи потратить еще 50 наносекунд на запрос?». Сразу можно прикинуть, что это порядка 5% деградация в самом простом случае, что — много.

А помимо железа и размера спейсов есть еще море нюансов. Индекс — hash или tree (или rtree)? Индексируемое поле — число, строка, скаляр? Сколько полей в индексе? А сколько индексов? Запросы из lua или по сети (или по сети дергаем lua хранимку)? Записи делаем по одной или большими транзакциями? Сравнение строк бинарное или utf8 case insensitive? И это то, что первое пришло в голову.

Если интересны реальные цифры, то на моем почти десятилетнем десктопе все самое простое из вышеперечисленного в lua выдает около 0.5Mrps на запись и 1Mrps на чтение.

Information

Rating
Does not participate
Works in
Registered
Activity