我有一个包含4000行的.txt文件,我正在尝试将它们插入到mysql中,这里有两种方法可以做同样的事情,第一种方法是这样简单地编码的:
$start = microtime(true);
foreach($b as $k=>$v){//$b is an array of 4,000 elements
$db->exec("INSERT INTO siji (en,cn) VALUES ('$v[0]','$v[1]')");
}
echo microtime(true)-$start;//116 sec.
第二种方法是使用pdo::bindparam(),我知道对于重复的sql查询,最好使用bindparam(),因为每个查询之间的唯一区别是它们的值,所以我这样编码:
$start = microtime(true);
$stmt = $db->prepare('INSERT INTO siji (en,cn) VALUES (:en,:cn)');
$stmt->bindParam(':en',$en);
$stmt->bindParam(':cn',$cn);
foreach($b as $k=>$v){//$b is an array of 4,000 elements
$en = $v[0];
$cn = $v[1];
$stmt->execute();//
}
echo microtime(true)-$start;//127 sec.
第二种方法比第一种方法快得多,结果并不像我想象的那样,有人能告诉我bindparam()真的加快了批量插入吗?或者在使用bindParam()时可能出现什么问题?
最佳答案
您还没有指定要使用的数据库服务器,所以我假设是mysql,因为它是最常见的。
要直接回答您的问题:答案是肯定的,pdo的prepare
函数应该使用db的prepared statements功能,这样在运行一批类似的查询时,结果会快得多。
不过,对于mysql pdo驱动程序,它默认模拟准备好的语句,而不是实际正确使用它们。
这意味着在默认情况下,在pdo对象内部,它基本上执行与第一个代码示例完全相同的操作,手动构建sql字符串。
我不知道为什么这是默认行为(可能是与旧版本mysql的兼容性问题?),但要防止这种情况并强制pdo正确使用准备好的语句,需要禁用此选项。
您可以执行以下操作:
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
试试看,看看会发生什么。
顺便说一下,如果您的.txt文件有4000行恰好是一个csv或其他常规格式的文件,那么您可以使用mysql内置的
LOAD DATA INFILE
函数,该函数可以通过一个查询将整个文件加载到db中。这总是比在php中循环相同查询4000次所能达到的任何速度都快得多。(其他数据库具有类似的功能)。关于php - php bindParam()会加速批量插入吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17086663/