【问题标题】:Batch insertion of data to MySQL database using php使用php批量插入数据到MySQL数据库
【发布时间】:2009-06-25 06:47:48
【问题描述】:

我有数以千计的数据从巨大的 XML 中解析出来,并使用 PHP 和 MySQL 插入到数据库表中。我的问题是将所有数据插入表中需要很长时间。有没有办法将我的数据分成更小的组,以便插入过程按组进行?例如,如何设置一个将数据处理 100 的脚本?这是我的代码:

foreach($itemList as $key => $item){
     $download_records  = new DownloadRecords();
    //check first if the content exists
    if(!$download_records->selectRecordsFromCondition("WHERE Guid=".$guid."")){
         /* do an insert here */
    } else {
         /*do an update */
    }

}

*注意:$itemList 大约有 62,000 个并且还在增长。

【问题讨论】:

    标签: php mysql load-data-infile


    【解决方案1】:

    使用 for 循环?

    但是将数据加载到 MySQL 的最快选择是使用 LOAD DATA INFILE 命令,您可以创建文件以通过 PHP 加载,然后通过不同的进程将其提供给 MySQL(或作为原始进程的最后一步) )。

    如果您不能使用文件,请使用以下语法:

    insert into table(col1, col2) VALUES (val1,val2), (val3,val4), (val5, val6)
    

    因此您可以减少要运行的句子总数。

    编辑:鉴于您的 sn-p,您似乎可以从 MySQL 的 INSERT ... ON DUPLICATE KEY UPDATE 语法中受益,让数据库完成工作并减少查询量。这假设您的表具有主键或唯一索引。

    要每 100 行访问一次数据库,您可以执行以下操作(请查看并修复您的环境

    $insertOrUpdateStatement1 = "INSERT INTO table (col1, col2) VALUES ";
    $insertOrUpdateStatement2 = "ON DUPLICATE KEY UPDATE ";
    $counter = 0;
    $queries = array();
    
    foreach($itemList as $key => $item){
        $val1 = escape($item->col1); //escape is a function that will make 
                                     //the input safe from SQL injection. 
                                     //Depends on how are you accessing the DB
    
        $val2 = escape($item->col2);
    
        $queries[] = $insertOrUpdateStatement1. 
        "('$val1','$val2')".$insertOrUpdateStatement2.
        "col1 = '$val1', col2 = '$val2'";
    
        $counter++;
    
        if ($counter % 100 == 0) {
            executeQueries($queries);
            $queries = array();
            $counter = 0;
        }
    }
    

    executeQueries 会抓取数组并发送单个多重查询:

    function executeQueries($queries) {
       $data = "";
         foreach ($queries as $query) {
            $data.=$query.";\n";
        }
        executeQuery($data);
    }
    

    【讨论】:

    • 是的,我正在使用 for 循环将数据插入远程数据库。还有一个问题是我使用的是远程数据库,所以我的脚本在单独的服务器上运行以提供另一个数据库在单独的服务器上运行。
    • 使用你能处理的最少的句子,即使用大的插入语句。
    • 是的,我可以使用文件,这就是我的计划。我担心插入,我如何重复插入表(col)VALUES(val)以在 100 行后重复到达了吗?
    • 使用模运算符。 for ($i = 0; $i
    • 我看到你正在使用 foreach,添加一个外部计数器。
    【解决方案2】:

    是的,做你想做的事。

    如果您认为您可能会遇到超时等问题,则不应尝试从 Web 应用程序进行批量插入。而是将文件放在某处并有一个守护程序或 cron 等,将其拾取并运行批处理作业(如果从cron,请确保一次只运行一个实例)。

    【讨论】:

      【解决方案3】:

      你应该把它放在一个临时目录中,用一个 cron 作业来处理文件,以避免超时(或用户失去网络)。

      仅使用网络进行上传。

      如果您真的想通过网络请求导入数据库,您可以进行批量插入或至少使用一个更快的事务。

      然后以 100 个为单位限制插入(如果计数器为 count%100==0,则提交您的事务)并重复直到插入所有行。

      【讨论】:

      • 如何实现$count%100=0?我使用一个文件在我的目标表中转储数据。 INSERT INTO table VALUES(val), (val).... (val);并在行数达到 100 后重复 INSERT 吗?
      • 例如:cnx = mysql_connect() x=0 while(要插入的东西)做:fetch_values_from_file(X,Y,Z) cnx.exec("insert into table values X,Y,Z" ,X,Y,Z) x += 1 如果 x % 100 : cnx.commit()
      猜你喜欢
      • 2014-11-03
      • 2016-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-27
      • 1970-01-01
      • 2015-03-25
      • 2011-01-14
      相关资源
      最近更新 更多