有没有办法在不到 12000 分钟的时间内从 txt 文件更新 2+ 行?

Is there a way to update 12000+ rows from txt file in less then 2mins?

提问人:nab 提问时间:7/25/2019 最后编辑:Claudionab 更新时间:7/25/2019 访问量:176

问:

我需要使用 php Codeigniter 和 txt 文件更新一个超过 12000 行的表。.读取文件和循环都很好,但是当逐行更新时,大约需要 30 分钟,我想问题是我正在按名称搜索,因为我在 txt 文件中没有 id...... 这是我的代码:foreach

控制器:

$fn = fopen($this->upload->data('full_path'),"r");

$update = true;
while(! feof($fn) && $update)  {
    $pieces = explode("|", fgets($fn));
    if(sizeof($pieces) == 9 && is_numeric(trim($pieces[1]))) {
        $update = $this->model_products->update3s($pieces);
    }
} 

fclose($fn);

型:

public function update3s($product) {
    if ($product) {
        $product[2] = trim(str_replace("'","''",$product[2]));
        $product[1] = trim($product[1]);
        $product[6] = trim($product[6]);
        $product[3] = trim($product[3]);
        $sql = "UPDATE products set qty = $product[3], price_vente = $product[6]  where (name = '$product[2]')";
        echo $sql.'<br>';
        $update = $query = $this->db->query($sql);
        return $update;
    }

    return false;
}
php mysql codeigniter mysqli

评论

0赞 Akshit Ahuja 7/25/2019
为表编制索引可以简单地减少时间
0赞 nab 7/25/2019
@AkshitAhuja我有一个主键(AI Int),但 TXT 文件中唯一唯一的就是名称。
2赞 jcheron 7/25/2019
向 添加唯一索引,使用参数化请求,在循环之前准备语句name
1赞 odan 7/25/2019
一些提示: * 在MySQL中禁用外键约束,临时 * 使用批量插入 * 使用预准备语句
1赞 Raymond Nijland 7/25/2019
如果更新一个表,则可以将多个更新语句与 CASE END cluase 合并,例如 ...请记住在“离线”数据上写入/测试它......此外,使用 TRANSACTION 可以加快多个更新查询的速度,并且不要忘记在更新的 WHERE 子句中使用的列的索引。UPDATE table SET qty =(CASE WHEN name = 'product_1' THEN 1 ELSE NULL END) WHERE name IN(...)

答:

4赞 potiev 7/25/2019 #1

您可以使用事务并为数据库表中的列添加索引。name

$fn = fopen($this->upload->data('full_path'),"r");

$update = true;

$updatedCount = 0;

while(! feof($fn) && $update)  {
    $pieces = explode("|", fgets($fn));
    if(sizeof($pieces) == 9 && is_numeric(trim($pieces[1]))) {
      if ($updatedCount == 0) {
         $databaseInstance->beginTransaction();
      }
      $update = $this->model_products->update3s($pieces);
      ++$updatedCount;

      if ($updatedCount > 500) { //in one transaction update 500 rows
         $databaseInstance->commit();
         $updatedCount = 0;
      }
    }
} 

if ($updatedCount > 0) { // if we have not commited transaction 
   $databaseInstance->commit();
}

fclose($fn);
3赞 odan 7/25/2019 #2

一些提示

  • 向字段添加索引name
  • 使用预准备语句
  • 禁用 MySQL 伪造密钥检查 阅读更多
1赞 Swarna Sekhar Dhar 7/25/2019 #3

编写 SQL 函数甚至可以在更短的时间内做到这一点。 使用以下功能:

在 MySQL 用户定义函数

CREATE FUNCTION update3s(hole_file_content LONGTEXT) RETURNS Boolean
BEGIN 
                    -----Your implementation(same logic in sql ) ------ 
END

然后通过它是否是 CI 3 来整理它

$this->db->call_function('update3s', file_get_contents($this->upload->data('full_path')));

$this->db->query("select update3s(".file_get_contents($this->upload->data('full_path')).")");