Самый быстрый способ вставить / обновить миллион строк в Laravel 5.7 - PullRequest
0 голосов
/ 22 октября 2018

Я использую Laravel 5.7, чтобы получать большие объемы данных (около 500 тыс. Строк) с сервера API и вставлять их в таблицу (назовите это Таблица A) довольно часто (по крайней мере, каждые шесть часов, 24/7) -тем не менее, достаточно вставить только изменения в следующий раз, когда мы вставим (но по крайней мере 60-70% элементов будут изменены).Таким образом, эта таблица будет быстро содержать десятки миллионов строк.

Мне пришла в голову идея создать вспомогательную таблицу (назовите ее Таблица B) для хранения в ней всех новых данных.Прежде чем вставить все в таблицу A, я хочу сравнить ее с предыдущими данными (с Laravel, PHP) из таблицы B - поэтому я буду вставлять только те записи, которые необходимо обновить.Опять же, как правило, это будет около 60-70% записей.

Мой первый вопрос - если этот вышеупомянутый способ является предпочтительным способом сделать это в этой ситуации (очевидно, яЯ хочу, чтобы это произошло как можно быстрее. Я предполагаю, что поиск обновления записей в таблице займет гораздо больше времени, и таблица будет занята / заблокирована.Есть ли лучший способ добиться того же (имеется в виду, чтобы обновить записи в БД).


Вторая проблема, с которой я сталкиваюсь, это медленное время вставки.Прямо сейчас я использую локальную среду (16 ГБ ОЗУ, процессор I7-6920HQ), и MySQL вставляет строки очень медленно (около 30-40 записей одновременно).Размер одного ряда составляет около 50 байтов.

Я знаю, что это можно сделать намного быстрее, поиграв с настройками InnoDB.Тем не менее, я также хотел бы подумать, что я могу сделать что-то на стороне Laravel для повышения производительности.

Сейчас мой код Laravel выглядит следующим образом (вставляя только 1 запись за раз):

foreach ($response as $key => $value)
{
    DB::table('table_a')
        ->insert(
        [
            'test1' => $value['test1'],
            'test2' => $value['test2'],
            'test3' => $value['test3'],
            'test4' => $value['test4'],
            'test5' => $value['test5'],
        ]);
}

$response - это тип массива.

Итак, мой второй вопрос: Есть ли способ увеличить время вставки записей примерно до 50k / сек - обана прикладном уровне Laravel (путем пакетной вставки) и на уровне MySQL InnoDB (изменение конфигурации).

Текущие настройки InnoDB:

innodb_buffer_pool_size        = 256M
innodb_log_file_size           = 256M
innodb_thread_concurrency      = 16
innodb_flush_log_at_trx_commit = 2
innodb_flush_method            = normal
innodb_use_native_aio = true

Версия MySQL 5.7.21.

Если я забыл сказать / добавить что-либо, пожалуйста, дайте мне знать в комментарии, и я сделаю это быстро.

Редактировать 1: Сервер, который я планирую использоватьбудет иметь SSD на нем - если это имеет какое-либо значение.Я предполагаю, что вставки MySQL будут по-прежнему считаться вводом / выводом.

1 Ответ

0 голосов
/ 22 октября 2018

Не вызывайте insert() внутри foreach(), потому что он выполнит n number of queries для базы данных, когда у вас есть n number of data.

Сначала создайте массив объектов данных, соответствующих столбцу базы данныхимена.и затем передайте созданный массив в функцию insert().

Это только выполнит запрос one к базе данных, независимо от того, сколько у вас данных.

Это намного быстрее,слишком быстро.

$data_to_insert = [];

foreach ($response as $key => $value)
{
    array_push($data_to_insert, [
            'test1' => $value['test1'],
            'test2' => $value['test2'],
            'test3' => $value['test3'],
            'test4' => $value['test4'],
            'test5' => $value['test5'],
    ]);
}

DB::table('table_a')->insert($data_to_insert);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...