Node.js and MongoDB: transactions performance

Novokhatskyi Oleksii
4 min readJul 19, 2020

Epigraph

Sometimes we pay the most for what we get for free. ― Albert Einstein
Everything in this world must be measured. Numbers are the only source of truth. Don’t trust anyone, don’t trust yourself. Measure. ― Me

Problem?

Database transaction is the important part of a lot of applications. Sometimes it’s a critical part of business logic and in such cases performance of transactions can become a major metric.

In MongoDB 4+ we got multi-document transactions support. But what about performance? Will we go slower? Let’s find out!

Questions need answers

Do transactions affect the speed of basic MongoDB operations?

Do transactions affect the speed of the sequence of operations?

Is there a difference in the speed of the main MongoDB operations (and their combination) with and without transactions?

What is the difference in the speed of the main MongoDB operations (and their combination) with and without transactions?

Implementation: Step 1 (tools)

  1. We used MongoDB v4.0.3 (module “mongodb-memory-server”) ― replica set (with minimal number of mongod processes)
    https://www.npmjs.com/package/mongodb-memory-server
  2. Using MongoDB driver v3.3.4 (module “mongodb”)
    https://www.npmjs.com/package/mongodb
  3. Something is needed to get the data (we used the “microseconds” module)
    https://www.npmjs.com/package/microseconds
  4. The data needs to be analyzed (we use the “ttest” module) and “beautifully” drawn (the module “@stdlib/stdlib”)
    https://www.npmjs.com/package/ttest
    https://www.npmjs.com/package/@stdlib/stdlib
  5. The process of data collecting will take a long time (believe me), because something is needed for beauty and visibility (the “progress-barjs” module)
    https://www.npmjs.com/package/progress-barjs
  6. Still have to write code(

Implementation: Step 2 (results)

Implement the basic operations of MongoDB ― insertOne, updateOne, deleteOne, findOne, insertMany*, updateMany*, deleteMany*, find*; and their combination ― insertOne + updateOne + deleteOne, insertOne + updateOne + deleteOne + findOne, insertMany* + updateMany* + deleteMany*, insertMany* + updateMany* + deleteMany* + find* with and without the use of transactions

Measure the execution time of each operation

Example (insertMany + updateMany + deleteMany operation) with and without transaction:

Perform each operation / time measurement by iterations 300 times (for the subsequent analysis, 100 “average” measurements from 101 to 200 will be used)*

Perform operations in a random sequence in the amount of 100 iterations**

* “many” = 300 (selected purely empirically)
** for more info about implementation, please, visit github repository (link is in the end of this article)

Implementation: Step 3 (analysis)

We save the data for each operation in arrays (a total of 20,000 measurements per operation ― 10,000 using transactions, 10,000 without) so let’s make a small statistical analysis

Trim values ​​that fall outside the selection boundaries

Calculate average

Calculate standard deviation

Determine if there is a statistically significant difference between samples with ttest

What is the average difference between performing each type of operation and in whose favor?

The picture below describes the results of one combination of the operations (insertMany + updateMany + deleteMany) and insertOne operation. For other operations result looks the same and described in conclusion section. Here we have the name of operation(s) (insertManyUpdateManyDeleteMany and insertOne), mean with standard deviation (teal ― without transaction, orange ― with transaction), “Is statistically significant” means that there is some difference between with / without transaction performance and how operations with transaction are slower of faster in percentages

insertManyUpdateManyDeleteMany results

Conclusion

In general, it makes no difference: insertMany + updateMany + deleteMany (look for illustration above)

There is a difference, well, this (up to 7%): updateMany, find, insertOne + updateOne + deleteOne + findOne, insertMany + updateMany + deleteMany + find

Transactions are slower, but not so much (up to 91%): updateOne, deleteMany, findOne

Transactions are much slower (from 197% to 792%): insertOne, insertMany, deleteOne, insertOne + updateOne + deleteOne

I’m sure that there will be some major changes in future versions of MongoDB and they’ll improve the performance of the transactions (and we’ll have additional cause for new measurement).

For more info and to have possibility to check results by running scripts by yourself ― please, visit github repository.

Thanks for reading.
Please clap and follow me so as not to miss new articles.

Feel free to comment, hope we’ll have a good discussion.
Also you are able to run this script by yourself and get own results, will be cool to compare different results.

--

--