When using the NodeJS mysql2 library, I am trying to understand the differences between Connection.execute and Connection.query.
As I understand it, query
prepares the statement locally and then makes one call to the database. execute
sends the query without parameters to the database to be prepared then sends the parameters separately to be executed with the prepared statement.
Where my understanding really falls apart is how or if the statement gets cached when using Connection.execute
. Does calling Connection.execute
twice in a row with the same query have any benefit?
In function B1
below, the statement gets re-used, which gives a performance improvement.
However in function B2
, does the statement get re-used, or are there four separate network calls being made to the database? In the case there is no re-use of the statement in B2
, would B3
be the fastest option?
async function B1(connection) {
const statement = await connection.prepare("SELECT 1 + ? + ?");
const result1 = await statement.execute([1, 2]);
const result2 = await statement.execute([3, 4]);
await statement.close();
return [result1, result2];
}
async function B2(connection) {
const result1 = await connection.execute("SELECT 1 + ? + ?", [1, 2]);
const result2 = await connection.execute("SELECT 1 + ? + ?", [3, 4]);
return [result1, result2];
}
async function B3(connection) {
const result1 = await connection.query("SELECT 1 + ? + ?", [1, 2]);
const result2 = await connection.query("SELECT 1 + ? + ?", [3, 4]);
return [result1, result2];
}
Where my understanding really falls apart is how or if the statement gets cached when using Connection.execute. Does calling Connection.execute twice in a row with the same query have any benefit?
According to the documentation it does:
MySQL2 provides execute helper which will prepare and query the statement. You can also manually prepare / unprepare statement with prepare / unprepare methods.
The example they give is
import mysql from 'mysql2/promise';
try {
// create the connection to database
const connection = await mysql.createConnection({
host: 'localhost',
user: 'root',
database: 'test',
});
// execute will internally call prepare and query
const [results, fields] = await connection.execute(
'SELECT * FROM `table` WHERE `name` = ? AND `age` > ?',
['Rick C-137', 53]
);
console.log(results); // results contains rows returned by server
console.log(fields); // fields contains extra meta data about results, if available
} catch (err) {
console.log(err);
}
and the tip
If you execute same statement again, it will be picked from a LRU cache which will save query preparation time and give better performance.
LRU cache: Cache replacement algorithms are efficiently designed to replace the cache when the space is full. The Least Recently Used (LRU) is one of those algorithms. As the name suggests when the cache memory is full, LRU picks the data that is least recently used and removes it in order to make space for the new data. The priority of the data in the cache changes according to the need of that data i.e. if some data is fetched or updated recently then the priority of that data would be changed and assigned to the highest priority , and the priority of the data decreases if it remains unused operations after operations.
So it is cached and eventually be forgotten if the cache is full and it is the least recent entry, but until then it will be reusable.