MySQLi多行插入非常慢

时间:2015-02-18 19:58:02

标签: php mysql mysqli wamp innodb

我在WAMP中有一个InnoDB表,其中包含大约4千万条具有以下结构的记录:

CREATE TABLE sales (
  sale_id int(12) unsigned NOT NULL,
  sale_type_id int(12) unsigned NOT NULL,
  sale_employee_id int(12) unsigned NOT NULL,
  sale_period tinyint(3) unsigned NOT NULL,
  sale_minute tinyint(3) unsigned NOT NULL,
  sale_second tinyint(3) unsigned NOT NULL,
  sale_amount decimal(5,2) unsigned NOT NULL,
  PRIMARY KEY (sale_id, sale_type_id),
  KEY (sale_employee_id, sale_type_id, sale_period, sale_amount, sale_minute)
)

我使用MySQLi一次使用数组和#34; implode"一起插入大约3,000条新记录,如下所示,需要1到2分钟才能完成:

$insertArray = array();
foreach($phpArray->sales as $sale) {
    $saleId = (int) $saleId;
    $saleType = (int) $saleType;
    $saleEmployeeId = (int) $saleEmployeeId;
    $salePeriod = (int) $salePeriod;
    $saleMinute = (int) $saleMinute;
    $saleSecond = (int) $saleSecond;
    $saleAmount = $saleAmount;

    $insertArray[] = "('$saleId', '$saleType', '$saleEmployeeId', '$salePeriod', '$saleMinute', '$saleSecond', '$saleAmount')";
}

$insertSql = "INSERT IGNORE INTO sales (sale_id, sale_type_id, sale_employee_id, sale_period, sale_minute, sale_second, sale_amount) VALUES ".implode(",",$insertArray);
$insertResult = $mysqli->query($insertSql);

我这样做的方式有什么明显的错误吗?

INSERT IGNORE会明显慢于INSERT吗? 我有复合PRIMARY KEY的事实可能是个问题吗? 我是否需要在插入数组中的每个变量名称周围使用引号,如果不是,那么删除它们会加快速度吗?

提前感谢任何建议!

5 个答案:

答案 0 :(得分:1)

我有类似的问题。关闭自动提交并在一个请求中手动提交解决了我的问题。

$mysqli->autocommit(FALSE);
// loop through all the new records
foreach($newRecordsArray as $newRecord) {
... do your foreach loop per record here.....             
    $insertResult = $mysqli->query($insertSql);
}
//do one commit     
if (!$mysqli->commit()) {
    print("Transaction commit failed\n");
    exit();
}

答案 1 :(得分:0)

使用insert插入那么多行总是很慢。 Insert ignore只是通过跳过那些插入而不是抛出错误并停止整个批处理来忽略重复错误,这样就不会让它变慢:插入那么多行是什么?让它变慢。

要快速插入那么多行,请在mysql控制台中使用load data infile,如果可以的话。

也可以从PHP应用程序中使用load data LOCAL infile,具体取决于用于连接MySQL的用户的权限。

答案 2 :(得分:0)

INSERT IGNOREINSERT快。 您可以直接连接字符串,而不是创建数组并对其进行插入。它应该更有效率。

复合主键在插入新行时比普通id键花费更多,因为它基于MySQL(或哈希索引)中的B-TREE方法

答案 3 :(得分:0)

尝试更改:

$insertResult = $mysqli->query($insertSql);

为:

$mysqli->query("START TRANSACTION");
$insertResult = $mysqli->query($insertSql);
$mysqli->query("COMMIT");

这可能让你大吃一惊: - )

答案 4 :(得分:0)

是的,当执行许多自动提交的查询是有害的时,请使用以下方法:

$mysqli->autocommit(FALSE);
$mysqli->begin_transaction(MYSQLI_TRANS_START_READ_WRITE);

// multiple inserts here

$mysqli->commit();

顺便说一句,您可以通过查询检查自动提交状态:

$mysqli->query("SELECT @@autocommit")