0

我必须每次将 1000 行数据插入 MySQL。目前,我使用 PDO 和 for-loop 将逐行插入数据库。有没有更有效的方法来获得更好的性能?因为我必须将 max_execution_time 设置为 5 分钟。

function save()
{
            return $query = $this->insert("
                INSERT INTO gadata (landing_page, page_title, page_views, visits, visitors, bounce_rate, pageviews_per_visit, time_on_page, avg_time_on_page, day, month, year, hour)
                VALUES (:landing_page, :page_title, :page_views, :visits, :visitors, :bounce_rate, :pageviews_per_visit, :time_on_page, :avg_time_on_page, :day, :month, :year, :hour)", $this->data);
}

protected function insert($sql, array $data) {
    $q = $this->_db_handler->prepare($sql);

    foreach ($data as $k => $v)
    {
       $q->bindValue(':' . $k, $v);
    }

    $q->execute();
}
4

3 回答 3

2

它不是 PDO,也不是您插入的方式使插入如此延迟,而是innodb引擎。所以你有3个选择:

  1. 将所有插入包装到事务中。
  2. 使用 root 权限,将innodb_flush_log_at_trx_commit变量设置为 2,使 innodb 使用文件缓存进行写入 - 这将使您的插入速度非常快。
  3. 按照 Manu 的建议在一个查询中运行所有插入
于 2013-04-07T13:28:48.600 回答
1

Might not be the best solution, But you can try constructing a query string like INSERT INTO [table] VALUES (r1c1,r1c2,r1c3),(r2c1,r2c2,r2c3) ... and execute one mysql_query (or say one query for few hundred rows), you might even verify data programatically while constructing the sql query if it is not from a trusted source.

于 2013-04-07T12:59:29.267 回答
1

参数化查询根据定义交易执行安全性,以降低数据项计数的灵活性。

您至少有 2 种可能性来缓解:

  • 构建 SQL,然后立即执行它:

就像是:

$sql="INSERT INTO gadata (landing_page, page_title, page_views, visits, visitors, bounce_rate, pageviews_per_visit, time_on_page, avg_time_on_page, day, month, year, hour) VALUES ";
foreach ($all_data_rows as $data) {
  if ($i==0) $value=""; else $value=",";
  $sql.=$value."(:landing_page$i, :page_title$i, :page_views$i, :visits$i, :visitors$i, :bounce_rate$i, :pageviews_per_visit$i, :time_on_page$i, :avg_time_on_page$i, :day$i, :month$i, :year$i, :hour$i)";
  $i++;
}
$i=0;
$q=$db_handler->prepare($sql);
foreach ($all_data_rows as $data) {
  foreach ($data as $k => $v) {
    $q->bindValue(":$k$i", $v);
  }
  $i++;
}
$q->execute();
  • 使用临时表来避免锁定和磁盘开销

首先创建一个HEAP与目标表具有相同结构的临时表,然后插入其中:这会快得多,因为不会发生锁定和磁盘 IO。然后运行

INSERT INTO final_table SELECT * FROM temporary_table

如果缓解还不够,您将需要考虑为此用例使用非参数化查询。通常的警告适用。

于 2013-04-07T13:06:40.983 回答