@gvg1

Как записать массив PHP в базу данных MySQL?

Имеется массив массивов $m и таблица БД из трёх (упрощённо) элементов (полей) - mediumint, mediumint и varchar.
Имею 3 рабочих варианта записать массив в БД.
Но все они примерно одинаково медленные.
Как ускориться?
Можно без PDO или без одного из циклов или с циклом другого вида (значения числовых полей не непрерывные, были удаления элементов) или вообще без циклов одним INSERT'ом (здесь смайлик) или ещё как-то.
$pdo=new PDO("mysql:host=$host;dbname=$dbname;charset=$charset",$username,$password);
$insert='INSERT INTO table1 (i1,i2,s1) VALUES (:i1,:i2,:s1)';
$q=$pdo->prepare($insert);
foreach ($m as $key=>$value){
  foreach ($value as $value1){
    $q->bindParam(':i1',$key,PDO::PARAM_INT);
    $q->bindParam(':i2',$value1[0],PDO::PARAM_INT);
    $q->bindParam(':s1',$value1[1],PDO::PARAM_STR);
    $q->execute();
  };
};

$pdo=new PDO("mysql:host=$host;dbname=$dbname;charset=$charset",$username,$password);
foreach ($m as $key=>$value){
  foreach ($value as $value1){
    $insert='INSERT INTO table1 (i1,i2,s1) VALUES ('.$key.','.$value1[0].",'".$value1[1]."')";
    $q=$pdo->prepare($insert);
    $q->execute();
  };
};

$pdo=new PDO("mysql:host=$host;dbname=$dbname;charset=$charset",$username,$password);
foreach ($m as $key=>$value){
  foreach ($value as $value1){
    $insert="INSERT INTO table1 (i1,i2,s1) VALUES ({$key},{$value1[0]},'{$value1[1]}')";
    $q=$pdo->prepare($insert);
    $q->execute();
  };
};


UPD:
Наткнулся на вариант: записать массив в текстовый файл и командой LOAD DATA INFILE загрузить оный в базу. Может будет быстрее.
  • Вопрос задан
  • 176 просмотров
Решения вопроса 2
rozhnev
@rozhnev Куратор тега PHP
Fullstack programmer, DBA, медленно, дорого
Если массив не очень большой - сделайте всё одним запросом:
<?php
$data = [
    ['a' => 1, 'b' => 2, 'c' => 3],
    ['a' => 1, 'b' => 2, 'c' => 3],
    ['a' => 1, 'b' => 2, 'c' => 3],
    ['a' => 1, 'b' => 2, 'c' => 3],
    ['a' => 1, 'b' => 2, 'c' => 3]
];

$query="INSERT INTO t (a, b, c) VALUES " . implode(
    ', ', 
    array_fill(
        0,
        count($data), 
        '(' . implode (', ', array_fill(0, count($data[0]), '?')) . ')'
    )
);

echo $query;

$values = array_reduce(
    $data,
    function($ac, $el) {
        return array_merge($ac, array_values($el));
    },
    []
);

var_export($values);

$q=$pdo->prepare($query);
$q->execute($values);


Здесь вы можете протестировать код
Ответ написан
ipatiev
@ipatiev Куратор тега PHP
Потомок старинного рода Ипатьевых-Колотитьевых
Ответ на вопрос, который вы почему-то решили вынести в заголовок (при том что, судя по тексту вопроса, вы прекрасно знаете ответ на него) - и который имеет очень мало общего с вашей реальной проблемой - уже дал Slava Rozhnev.

Если же говорить про проблему медленной записи, то она происходит из того факта, что mysql по умолчанию убеждается в успешности записи каждой строки, перед тем как записывать следующую. Отсюда будут и варианты её решения

Вариант 1, при котором никакой код менять не надо. Отключаем эти проверки устанавливая переменную mysql innodb_flush_log_at_trx_commit=0. Для этого надо обладать правами рута.
Вариант 2: заключить все вставки в транзакцию
Вариант 3: добавлять все записи одним запросом. Это можно сделать либо кодом Slava Rozhnev, либо запросом LOAD DATA INFILE

Да, и между вашими вариантами 2 и три нет никакой разницы. Это один и тот же вариант, про который в любом случае надо забыть: он вообще никогда не должен применяться. Переменные должны попадать в запрос только через плейсхолдеры.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы