PHP PDO Mysql插入性能

PHP PDO Mysql插入性能,php,mysql,pdo,prepared-statement,innodb,Php,Mysql,Pdo,Prepared Statement,Innodb,我通常不会在PHP中使用很多SQL东西,但最近我的一个朋友强迫我使用它来帮助他调试一些东西 我使用PDO和PHP来插入一些数据,但是插入性能非常差。一个包含151个插入的简单循环几乎需要6秒钟!我不知道为什么 这是我的密码: <?php $database='XXXXXX'; $username='XXXXXX'; $password='XXXXXX'; $hostname='127.0.0.1'; $inserted=0; $counted=0; $dsn = 'mysql:dbna

我通常不会在PHP中使用很多SQL东西,但最近我的一个朋友强迫我使用它来帮助他调试一些东西

我使用PDO和PHP来插入一些数据,但是插入性能非常差。一个包含151个插入的简单循环几乎需要6秒钟!我不知道为什么

这是我的密码:

<?php

$database='XXXXXX';
$username='XXXXXX';
$password='XXXXXX';
$hostname='127.0.0.1';

$inserted=0;
$counted=0;
$dsn = 'mysql:dbname='.$database.';host='.$hostname.'';
$start=microtime(true);
try {
    $data = new PDO($dsn, $username, $password, array(PDO::ATTR_EMULATE_PREPARES => false));
} catch (PDOException $e) {
    echo('Connection failed: ' . $e->getMessage());
}
for($i=1;$i<=150;$i++) {
    $time=time();
    $query=$data->prepare("INSERT INTO `tbl_temp` (aid, bid) VALUES (?, ?)");
    $query->execute(array($i, $time));
}
$data=null;
print "Took: ".(microtime(true)-$start)." S to insert $i records\n";

// Took: 5.569482088089 S to insert 151 records <--- result
?>


我也使用bindParam尝试了相同的代码,速度大致相同。该服务器有一个8核Xeon处理器和64gb的RAM。脚本是从命令行(PHPCGI)运行的,数据库和表是新的、空的。数据库类型为InnoDB。有没有人能给我指出正确的方向,看看为什么它这么慢?因为我相信MySQL从来没有这么慢过

正如西蒙在评论中所说,在循环中做准备是没有用的。这样做将导致向数据库发送300个查询,每次一个用于准备,另一个用于实际插入。在之前使用prepare语句只会导致151个查询:

$query = $data->prepare("INSERT INTO `tbl_temp` (aid, bid) VALUES (?, ?)");
for ($i = 1; $i <= 150; $i++) {
    $time = time();
    $query->execute(array($i, $time));
}
$query=$data->prepare(“插入'tbl_temp'(辅助、投标)值(?)”;
对于($i=1;$i执行(数组($i,$time));
}
另一个想法是使用组合的多插入语句。我想它可能有更好的性能,但我不太确定:

$query = 'INSERT INTO `tbl_temp` (aid, bid) VALUES';
for ($i = 1; $i <= 150; $i++) {
    if ($i == 1) {
        $query .= ' ('.$i.', '.time().')';
    } else {
        $query .= ', ('.$i.', '.time().')';
    }
}
$data->exec($query);
$query='插入'tbl_temp'(援助、投标)值';
对于($i=1;$i exec($query);

正如Simon在评论中所述,在循环中进行准备是没有用的。这样做将导致300个查询被发送到数据库,每次一个查询用于准备,另一个查询用于实际插入。之前使用prepare语句只会导致151个查询:

$query = $data->prepare("INSERT INTO `tbl_temp` (aid, bid) VALUES (?, ?)");
for ($i = 1; $i <= 150; $i++) {
    $time = time();
    $query->execute(array($i, $time));
}
$query=$data->prepare(“插入'tbl_temp'(辅助、投标)值(?)”;
对于($i=1;$i执行(数组($i,$time));
}
另一个想法是使用组合的多插入语句。我想它可能有更好的性能,但我不太确定:

$query = 'INSERT INTO `tbl_temp` (aid, bid) VALUES';
for ($i = 1; $i <= 150; $i++) {
    if ($i == 1) {
        $query .= ' ('.$i.', '.time().')';
    } else {
        $query .= ', ('.$i.', '.time().')';
    }
}
$data->exec($query);
$query='插入'tbl_temp'(援助、投标)值';
对于($i=1;$i exec($query);

正如Simon在评论中所述,在循环中进行准备是没有用的。这样做将导致300个查询被发送到数据库,每次一个查询用于准备,另一个查询用于实际插入。之前使用prepare语句只会导致151个查询:

$query = $data->prepare("INSERT INTO `tbl_temp` (aid, bid) VALUES (?, ?)");
for ($i = 1; $i <= 150; $i++) {
    $time = time();
    $query->execute(array($i, $time));
}
$query=$data->prepare(“插入'tbl_temp'(辅助、投标)值(?)”;
对于($i=1;$i执行(数组($i,$time));
}
另一个想法是使用组合的多插入语句。我想它可能有更好的性能,但我不太确定:

$query = 'INSERT INTO `tbl_temp` (aid, bid) VALUES';
for ($i = 1; $i <= 150; $i++) {
    if ($i == 1) {
        $query .= ' ('.$i.', '.time().')';
    } else {
        $query .= ', ('.$i.', '.time().')';
    }
}
$data->exec($query);
$query='插入'tbl_temp'(援助、投标)值';
对于($i=1;$i exec($query);

正如Simon在评论中所述,在循环中进行准备是没有用的。这样做将导致300个查询被发送到数据库,每次一个查询用于准备,另一个查询用于实际插入。之前使用prepare语句只会导致151个查询:

$query = $data->prepare("INSERT INTO `tbl_temp` (aid, bid) VALUES (?, ?)");
for ($i = 1; $i <= 150; $i++) {
    $time = time();
    $query->execute(array($i, $time));
}
$query=$data->prepare(“插入'tbl_temp'(辅助、投标)值(?)”;
对于($i=1;$i执行(数组($i,$time));
}
另一个想法是使用组合的多插入语句。我想它可能有更好的性能,但我不太确定:

$query = 'INSERT INTO `tbl_temp` (aid, bid) VALUES';
for ($i = 1; $i <= 150; $i++) {
    if ($i == 1) {
        $query .= ' ('.$i.', '.time().')';
    } else {
        $query .= ', ('.$i.', '.time().')';
    }
}
$data->exec($query);
$query='插入'tbl_temp'(援助、投标)值';
对于($i=1;$i exec($query);

结果表明,是SQL server内部的设置导致了此问题。据我所知,事务提交设置为在每次写入时刷新到磁盘:

innodb_flush_log_at_trx_commit=0
这是新安装的默认ACID兼容设置

我将设置更改为此

innodb_flush_log_at_trx_commit=2
这只允许断电或操作系统崩溃来擦除事务缓冲区/日志,而不允许mysqld崩溃


对于某些需要ACID的“D”值为100%真的人,则应不使用此设置。

结果表明,是SQL server内部的设置导致了此设置。据我所知,事务提交设置为在每次写入时刷新到磁盘:

innodb_flush_log_at_trx_commit=0
这是新安装的默认ACID兼容设置

我将设置更改为此

innodb_flush_log_at_trx_commit=2
这只允许断电或操作系统崩溃来擦除事务缓冲区/日志,而不允许mysqld崩溃


对于某些需要ACID的“D”值为100%真的人,则应不使用此设置。

结果表明,是SQL server内部的设置导致了此设置。据我所知,事务提交设置为在每次写入时刷新到磁盘:

innodb_flush_log_at_trx_commit=0
这是新安装的默认ACID兼容设置

我将设置更改为此

innodb_flush_log_at_trx_commit=2
这只允许断电或操作系统崩溃来擦除事务缓冲区/日志,而不允许mysqld崩溃


对于某些需要ACID的“D”值为100%真的人,则应不使用此设置。

结果表明,是SQL server内部的设置导致了此设置。据我所知,事务提交设置为在每次写入时刷新到磁盘:

innodb_flush_log_at_trx_commit=0
这是新安装的默认ACID兼容设置

我将设置更改为此

innodb_flush_log_at_trx_commit=2
这只允许断电或操作系统崩溃来擦除事务缓冲区/日志,而不允许mysqld崩溃

对于某些需要ACID的“D”为100%真的人,则应不使用此设置。

找到了此设置。请尝试此设置

$query = $data->prepare("INSERT INTO `tbl_temp` (aid, bid) VALUES (?, ?)");
try {
        $data->beginTransaction();
        for($i=0; $i < 150; $i++) {
            $time = time();
            $query->bindValue(1, $i, PDO::PARAM_INT);
            $query->bindValue(2, $time, PDO::PARAM_STR);
            $query->execute();
        }
        $data->commit();
    } catch(PDOException $e) {
            $data->rollBack();
    }
$query=$data->prepare(“插入'tbl_temp'(辅助、投标)值(?)”;
试一试{
$data->beginTransaction();
对于($i=0;$i<150;$i++){
$time=time();
$query->bindValue(1,$i,PDO::PARAM_INT);
$query->bindValue(2$time,PDO::PARAM_STR);
$query->execute();
}
$data->commit();
}捕获(PDO$e){
$data->rollBack();
}
找到了这个..所以试试这个

$query = $data->prepare("INSERT INTO `tbl_temp` (aid, bid) VALUES (?, ?)");
try {
        $data->beginTransaction();
        for($i=0; $i < 150; $i++) {
            $time = time();
            $query->bindValue(1, $i, PDO::PARAM_INT);
            $query->bindValue(2, $time, PDO::PARAM_STR);
            $query->execute();
        }
        $data->commit();
    } catch(PDOException $e) {
            $data->rollBack();
    }
$query=$data->prepare(“插入'tbl_temp'(辅助、投标)值(?)”;
试一试{
$data->begintern