mscdex / esqlite

An SQLite binding for node.js with built-in encryption, focused on simplicity and (async) performance
MIT License
37 stars 1 forks source link

Description

An SQLite (more accurately SQLite3MultipleCiphers) binding for node.js focused on simplicity and (async) performance.

Current SQLite version: 3.46.0

When dealing with encrypted sqlite databases, this binding only supports the ChaCha20-Poly1305 cipher to keep things simple, secure, and working well across multiple platforms.

Available/Relevant special PRAGMAs:

Table of Contents

Implementation/Design Notes

The goal of this addon/binding is to provide a simple and consistent interface for interacting with SQLite databases. What that means on a technical level is:

Performance

When discussing performance (particularly node.js sqlite driver performance), it's important to reiterate that your mileage may vary and that it mostly boils down to how the sqlite database is accessed. Specifically I'm referring to synchronous vs. asynchronous. Both have their advantages and disadvantages and have different scaling properties.

Because esqlite only provides an async API and the fact that sqlite directly accesses the disk, it means queries run in the thread pool to ensure the main thread is not blocked. With other types of databases where you make a network connection to the database, this is unnecessary and can be done without the thread pool (and without writing/using C/C++ code) because you're simply waiting for I/O, which node.js can easily and more efficiently do.

With that in mind, what this means is that for some workloads, synchronous queries will perform better than asynchronous queries because of the overhead of queueing work to the thread pool and the additional copying of results because you cannot access V8 APIs from threads in a node addon.

For benchmarking, I generated a single, unencrypted database with 100k records. The schema looked like:

CREATE TABLE data (
  ID INT,
  EmailAddress VARCHAR(500),
  FirstName VARCHAR(500),
  LastName VARCHAR(500),
  IPAddress VARCHAR(500),
  Age INT
)

The node.js version benchmarked with here was v20.14.0.

The sqlite packages being benchmarked:

Package Version
better-sqlite3 11.0.0
esqlite 0.0.18
sqlite3 5.1.7

Here is the code and the results for a couple of different queries that I ran on my Linux desktop:

Requirements

Installation

npm install esqlite

Examples

const db = new Database('/path/to/database'); db.open(); db.query(PRAGMA key = 'my passphrase', (err) => { if (err) throw err;

// Perform queries as normal ...

// ... and eventually close the database db.close(); });


* Binding values
```js
const { Database } = require('esqlite');

const db = new Database('/path/to/database');
db.open();

// Using nameless/ordered parameters
db.query('SELECT * FROM posts WHERE id = ?', [1234], (err, rows) => {
  if (err) throw err;

  db.close();
});

// Using named parameters
const values = { id: 1234 };
db.query('SELECT * FROM posts WHERE id = :id', { values }, (err, rows) => {
  if (err) throw err;

  db.close();
});

API

Exports


Database methods