Оптимизация запроса к базе данных — В цикле

Представьте, что у вас есть массив объектов
но в массиве некоторые объекты могут иметь несколько данных
например

const transactions = [
    {
        "player_id": 1,
        "transaction_id": "xxx",
        "amount": "100",
    },
    {
        "player_id": 2,
        "transaction_id": "xxx",
        "amount": "100",
    },
    {
        "player_id": 3,
        "transaction_id": "xxx",
        "amount": "100",
    },
    {
        "player_id": 1,
        "transaction_id": "xxx",
        "amount": "100",
    }
]
Вход в полноэкранный режим Выход из полноэкранного режима

и затем вам нужно получить информацию об игроке из базы данных

for (let i = 0; i<= transactions.length; i++) {
    const player = PlayerModel.findByPk(transactions[i].player_id)
// equals to SELECT * FROM users WHERE player_id = 1

    const saveTransaction = TransactionModel.create({
        id: transactions[i].transaction_id,
        player_id: transactions[i].player_id,
        player_before_balance: player.balance,
        player_after_balance: player.balance - transactions[i].amount
    });
}
Войти в полноэкранный режим Выйти из полноэкранного режима

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

open the db connection -> execute the query -> close the connection
Вход в полноэкранный режим Выйти из полноэкранного режима

Поэтому вместо такого способа можно выделить массив транзакций по идентификатору игрока

const distinctPlayers = [...new Set(transactions.map(transaction => transaction.player_id))] 
// result [1,2,3]
Вход в полноэкранный режим Выйти из полноэкранного режима

достаточно вызвать запрос к базе данных только 1 раз, используя условие where in, и сохранить его в переменной

const players = PlayerModel.findAll({
        where: {
            id: distinctPlayers
        }
    })
// equals to SELECT * FROM users WHERE player_id IN (1,2,3)

for (let i = 0; i<= transactions.length; i++) {
    const player = players.find(player => player.player_id === players.player_id);

    const saveTransaction = TransactionModel.create({
        id: transactions[i].transaction_id,
        player_id: transactions[i].player_id,
        player_before_balance: player.balance,
        player_after_balance: player.balance - transactions[i].amount
    });
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Но минус в том, что если массив слишком большой
память будет занимать слишком много.

Пожалуйста, скажите мне, если у вас есть лучший подход

Оцените статью
Procodings.ru
Добавить комментарий