javascriptprepared-statementmysql2node-mysql2

What's the benefit to using execute over query in mysql2?


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];
}

Solution

  • 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.