我已经尝试了一整天(再次),但错误地试图插入总共超过十亿行,而在一个查询中插入大约10k。我想用准备好的语句来做这个与MySQL,使用innoDB表。硬件资源不是问题,问题一直是索引和一行/插入。
不要说我应该直接使用列表方法,因为我需要在插入之前做一些计算。输入来自文件
我有一个大的while循环,循环文本文件行,这工作得很好。我目前做的是插入一个查询。
$stmt = $conn->prepare("INSERT INTO $tableName(row1, row2, row3) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $str1, $str2, $str3);
$stmt->execute();
我看过这样做的例子:
$stmt = $conn->prepare("INSERT INTO $tableName(row1, row2, row3) VALUES (?, ?, ?), (?, ?, ?), (?, ?, ?), (?, ?, ?) ..... ");
但是我需要为单个查询构建像5-10k行。
如果有人以前做过类似的事情,请提供一些参考。
提前感谢!
准备好的查询的整个思想是,它减少了每次运行查询时设置查询的开销——准备一次,重复执行。这意味着在循环中运行准备好的语句与传递一个大查询之间不会有很大的差异(从数据库的POV来看)。
这里没有包含整个代码,但是许多人犯的一个错误是在循环中包含语句准备。不要犯那个错误!像这样的代码将是最有效的:
// these need a value before being used in bind_param
$str1 = $str2 = $str3 = "";
$stmt = $conn->prepare("INSERT INTO $tableName(row1, row2, row3) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $str1, $str2, $str3);
while ($we_have_data) {
$str1 = "foo";
$str2 = "bar";
$str3 = "baz";
$stmt->execute();
}
虽然我总是建议使用PDO预处理语句,因为您可以避免绑定参数的潜在混乱:
// assuming $conn is a PDO object now
$stmt = $conn->prepare("INSERT INTO $tableName(row1, row2, row3) VALUES (?, ?, ?)");
while ($we_have_data) {
$str1 = "foo";
$str2 = "bar";
$str3 = "baz";
$stmt->execute([$str1, $str2, $str3]);
}
可能是因为限制了服务器的执行时间。尝试使用插入批处理。添加到数组
$i = 0;
.. looping
$i++;
$mark[] = '(?,?,?)';
$val[] = $str1.",".$str2.",".$str3;
// check when 1k record
if($i == 1000){
$stmt = $conn->prepare("INSERT INTO ? (row1, row2, row3) VALUES ".implode(',', $mark);
$stmt->bind_param("sss", implode(',', $val));
$stmt->execute();
$mark = []; $val = []; $i = 0; // reset
}