[Из песочницы] Node.js + MongoDB: перформанс транзакций
«Иногда мы платим больше всего за то, что получаем бесплатно.» — А.Эйнштейн
Не так давно в MongoDB версии 4+ появилась поддержка мульти-документных транзакций.
А поскольку наш проект как раз мигрировал на версию 4.2, закономерно возникли вопросы:
- Что будет с перформансом?
- На сколько операции замедлятся?
- Готовы ли мы пожертвовать скоростью ради (хоть какой-то) точности?
При изучении документации и интернетов вопросов только прибавилось:
- Все ли операции будут замедлены за счет транзакций?
- На сколько замедлятся комбинации операций?
Давайте попробуем узнать.
Для того, чтобы претендовать хотя бы на какую-то мизерную долю истины придется немного потрудиться.
Для простоты восприятия разделю имплементацию на 3 шага:
- Выбор инструментов
- Описание комбинаций операций и получения результатов
- Анализ результатов
Теперь о каждом шаге отдельно.
Выбор инструментов:
- Необходима тестовая MongoDB (реплика с минимальным количеством mongod процессов) и драйвер для нее: mongodb-memory-server, mongodb.
- Для простоты измерения времени я выбрал модуль «microseconds»
- Для анализа полученных результатов и визуализации используем следующее: ttest, stdlib.
Описание комбинаций операций и получения результатов:
Имплементируем каждую (из основных) отдельную операцию insertOne, updateOne, deleteOne, findOne, insertMany * updateMany * deleteMany * find * и их комбинации insertOne + updateOne + deleteOne, insertOne + updateOne + deleteOne + findOne, insertMany * + updateMany * + deleteMany * insertMany * + updateMany * + deleteMany * + find * с, и без использования транзакций.
Измерить время выполнения каждой операции.
Для примера — insertMany + updateMany + deleteMany с, и без транзакции
Каждую операцию / измерение повторим 300 раз (для анализа будем использовать 100 результатов «посередине», то есть с 101-го по 200-й) ** — назовем это «микроитерациямы» (итерациями отдельных операций или комбинаций).
Теперь, постоянно меняя последовательность, проведем 100 «макроитерации» (1 «макроитерация» = общее количество «микроитараций» * 300) *
* количество 300 выбрано абсолютно эмпирически
** для более полной информации об имплементации приглашаю посетить github репозиторий (ссылка ниже по тексту)
Анализ результатов:
В результате всех итераций мы получили 20000 замеров для каждой операции и комбинации операций (10000 с использованием транзакции, 10000 — без) в виде массивов
Далее необходимо провести некоторые расчеты.
Обрезать результаты, которые явно выпадают за пределы выборки
Вычислить среднее значение
Вычислить стандартное отклонение
Определить существование статистически достоверной разницы между выборками с помощью ttest (подтверждение или опровержение нулевой гипотезы)
С помощью простых графиков визуализируем результаты. Для примера возьмем комбинацию insertMany + updateMany + deleteMany и отдельно insertOne (все остальные результаты будут изложены в текстовом формате в разделе «Выводы»). В результате в сгенерированных html-файлах есть график, название которого соответствует названию операции или комбинации операции (бирюзовым цветом обозначены безтранзакционные итерации, оранжевым — транзакционные). «Is statistically significant» (true / false) говорит о том, была ли вообще какая-то статистически значимая разница. Все остальное — абсолютные и относительные значения в микросекундах и процентах соответственно.
Выводы:
- Вообще нет никакой разницы между операциями с использованием транзакций и без: insertMany + updateMany + deleteMany (ищите иллюстрацию выше)
- Существует небольшая разница (до 7%): updateMany, find, insertOne + updateOne + deleteOne + findOne, insertMany + updateMany + deleteMany + find
- Транзакции проходят медленнее, но не так критично (91%): updateOne, deleteMany, findOne
- Транзакции значительно медленнее (от 197% до 792%): insertOne, insertMany, deleteOne, insertOne + updateOne + deleteOne
Для получения дополнительной информации и возможности проверить результаты, запустив сценарии самостоятельно, посетите github.
Спасибо за то, что прочитали.
Не стесняйтесь комментировать, надеюсь, что у нас выйдет хорошая дискуссия.
Также вы можете запустить все это самостоятельно и получить собственные результаты. Будет круто их сравнить
Полезные ссылки:
medium.com/cashpositive/the-hitchhikers-guide-to-mongodb-transactions-with-mongoose-5bf8a6e22033
blog.yugabyte.com/are-mongodb-acid-transactions-ready-for-high-performance-applications
medium.com/@Alibaba_Cloud/multi-document-transactions-on-mongodb-4–0-eebd662ac237
www.mongodb.com/blog/post/mongodb-multi-document-acid-transactions-general-availability
docs.mongodb.com/manual/core/write-operations-atomicity
www.dbta.com/Columns/MongoDB-Matters/Limitations-in-MongoDB-Transactions-127057.aspx
dzone.com/articles/multi-document-transactions-on-mongodb-40
www.dbta.com/Columns/MongoDB-Matters/MongoDB-Transactions-In-Depth-125890.aspx
www.codementor.io/@christkv/mongodb-transactions-vs-two-phase-commit-u6blq7465
docs.mongodb.com/manual/core/read-isolation-consistency-recency
mathworld.wolfram.com/Outlier.html
support.minitab.com/en-us/minitab-express/1/help-and-how-to/basic-statistics/inference/how-to/two-samples/2-sample-t/interpret-the-results/key-results