Много запросов postgres (узел), нет параллельных запросов?

Я использую сервер узлов с пакетом postgres-node (pg).

Я написал программу, которая одновременно запрашивает n-запросов (например, 20 000) в моей базе данных postgres.

Когда я делаю это с несколькими клиентами, которые хотят одновременно запросить 20 000, параллелизма нет. Это означает, что запросы второго клиента будут поставлены в очередь, пока первый клиент не завершит все свои запросы.

Это нормальное поведение для postgres? Если да, как я могу предотвратить, чтобы один пользователь получил все ресурсы (а другие должны были ждать), если нет параллельности?

Это мой код:

const express = require('express');
const app = express();
const { Pool } = require("pg");
const pool = new Pool();


benchmark(){
    pool.connect((err, client, done) => {
      if (err) throw err;
      client.query("SELECT * from member where m_id = $1", [1], (err, res) => {
        done();
        if (err) {
          console.log(err.stack);
        } else {
          console.log(res.rows[0]);
        }
      });
    }); 
}


app.get('/', function(req, res) {
  for(let i=0;i<20000;i++){
    benchmark();
  }
});

1 ответ

Сначала вам нужно создать пул соединений, вот пример с pg узла в отдельном модуле (node-pg-sql.js) для удобства:

узел-Pg-sql.js:

const { Pool } = require('pg');

const pool = new Pool(fileNameConfigPGSQL);

module.exports = {
  query: (text, params, callback) => {
    const start = Date.now()
    return pool.query(text, params, (err, res) => {
      const duration = Date.now() - start
  //    console.log('executed query', { text, duration, rows: res.rowCount })
      callback(err, res)
    })
  },
  getClient: (callback) => {
    pool.connect((err, client, done) => {
      const query = client.query.bind(client)

      // monkey patch 
      client.query = () => {
        client.lastQuery = arguments
        client.query.apply(client, arguments)
      }

      // Timeout 5 sek
      const timeout = setTimeout(() => {
     //   console.error('A client has been checked out for more than 5 seconds!')
     //   console.error(`The last executed query on this client was: ${client.lastQuery}`)
      }, 5000)

      const release = (err) => {
        // 'done' Methode - returns client to the pool
        done(err)

        // clear Timeouts
        clearTimeout(timeout)

        // reset der Query-Method before Monkey Patch
        client.query = query
      }

      callback(err, client, done)
    })
  }
}

В вашем postgresql.conf (на linux обычно в /var/lib/pgsql/data/postgresql.conf) установите max-connection желаемое значение:

max_connection = 300

Иметь ввиду:

Каждое соединение PostgreSQL использует оперативную память для управления соединением или клиентом, использующим его. Чем больше у вас подключений, тем больше оперативной памяти вы будете использовать, чтобы вместо этого использовать ее для запуска базы данных.

Увеличивая ваши max-connectionsнужно увеличить shared_buffers а также kernel.shmmax а также для того, чтобы увеличение клиентского соединения было эффективным.

Всякий раз, когда вы хотите выполнить запрос с одного из ваших маршрутов / конечных точек, просто требуется отдельный файл пул клиента, например:

const db = require('../../../node-pg-sql');

module.exports = (router) => {

router.get('/someRoute', (req, res) => {
    console.log(`*****************************************`);
    console.log(`Testing pg..`);
    let sqlSelect = `SELECT EXISTS (
          SELECT 1 
          FROM   pg_tables
          WHERE  schemaname = 'someschema'
        )`;
    db.query(sqlSelect, (errSelect, responseSelect) => {
      if (errSelect) {
        /* INFO: Error while querying table */
        console.log(`*****************************************`);
        console.log(`ERROR WHILE CHECKING CONNECTION: ${errSelect}`);
      } 
      else {
        // INFO: No error from database
        console.log(`*****************************************`);
        console.log(`CONNECTION TO PGSQL WAS SUCCESSFUL..`);
        res.json({ success: true, message: responseSelect, data:responseSelect.rows[0].exists });

      }
    })
  });

}

РЕДАКТИРОВАТЬ:

"нет параллели.."

Узел асинхронный, вы можете работать с обещаниями или порождать больше клиентов / пулов и настраивать ваши max-соединения (как объяснено в моем ответе, но помните о производительности вашей хост-машины), но с несколькими клиентами, выполняющими около 20000 запросов, они не разрешатся с результатом мгновенно или параллельно. Какую именно цель вы пытаетесь достичь?

"Это нормальное поведение для postgres?"

Это связано с циклом событий узла, а также с определенным ограничением производительности хост-машины, на которой работает Postgres.

Другие вопросы по тегам