0

我的用例:

我有多个脚本以每秒几次插入的顺序插入到表中。我看到性能下降,所以我认为“批处理查询”和每分钟左右插入几百行会带来性能优势。

问题:

我将如何使用 mysqli 执行此操作?我当前的代码使用包装器(pastebin),看起来像:

$array = array();\\BIG ARRAY OF VALUES (more than 100k rows worth)
foreach($array AS $key => $value){
  $db -> q('INSERT INTO `player_items_attributes` (`column1`, `column2`, `column3`) VALUES (?, ?, ?)', 'iii', $value['test1'], $value['test2'], $value['test3']);
}

笔记:

我查看了使用事务,但听起来那些仍然会访问服务器,而不是排队。我更喜欢使用包装器(随意建议一个与我当前提供的功能相似的包装器),但如果不可能,我会尝试将建议构建到我使用的包装器中。

资料来源:

Wrapper 来自这里

编辑: 我正在尝试优化表速度,而不是脚本速度。该表有超过 3500 万行,并且有几个索引。

4

1 回答 1

1

MySQLINSERT语法允许一个INSERT查询插入多行,如下所示:

INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);

其中每组带括号的值代表表中的另一行。因此,通过处理数组,您可以在一个查询中创建多行。

有一个主要限制:查询的总大小不得超过配置的限制。对于 100k 行,您可能必须将其分解为 250 行的块,将 100k 查询减少到 400 个。您也许可以走得更远。

我不会尝试对此进行编码 - 您必须编写一些代码并在您的环境中尝试它。

这是一个伪代码版本:

escape entire array // array_walk(), real_escape_string()

block_size = 250; // number of rows to insert per query
current_block = 0;
rows_array = [];


while (next-element <= number of rows) {

    create parenthesised set and push to rows_array  // implode()

    if (current_block == block_size) {
        implode rows_array and append to query 
        execute query
        set current_block = 0
        reset rows_array
        reset query
    }
    current_block++
    next_element++
}

if (there are any records left over) {
    implode rows_array and append to query 
    execute the query for the last block
}

我已经可以想到使用 array_map() 可能更快的实现 - 试试看。

于 2013-07-09T04:30:01.080 回答