在将多个或批量插入查询更改为 PDO 时需要帮助

Posted

技术标签:

【中文标题】在将多个或批量插入查询更改为 PDO 时需要帮助【英文标题】:Need assistance in changing multiple or batch insert queries to PDO 【发布时间】:2013-01-06 14:39:19 【问题描述】:

我在此链接Is-there-a-better-way-to-process-a-300-000-line-text-file-data-and-insert-it-into-a-mysql-database 中提出了一个问题并发布了我的代码。

现在我想将查询更改为 PDO,但在更改 InsertData 函数中的查询时遇到了困难。我是 PDO 的新手,所以有人可以帮助我吗?不知道如何处理执行批量插入的插入语句。

我的想法是一一插入,但是我发布这个问题是为了提高性能效率吗?

//function for DB writing in table data
function InsertData($rec, &$errorDataCnt, &$sql, $y, $i, $x, &$dCnt)


    $dDate = (!isset($rec[0]) ? 0 : (trim($rec[0]) == "" ? 0 : trim($rec[0]))); 
    $dTime = (!isset($rec[1]) ? 0 : (trim($rec[1]) == "" ? 0 : trim($rec[1]))); 
    $address = (!isset($rec[2]) ? 0 : (trim($rec[2]) == "" ? 0 : trim($rec[2]))); 
    $co2SV = (!isset($rec[3]) ? 0 : (trim($rec[3]) == "" ? 0 : trim($rec[3]))); 
    $co2PV = (!isset($rec[4]) ? 0 : (trim($rec[4]) == "" ? 0 : trim($rec[4]))); 
    $tempSV = (!isset($rec[5]) ? 0 : (trim($rec[5]) == "" ? 0 : trim($rec[5]))); 
    $tempPV = (!isset($rec[6]) ? 0 : (trim($rec[6]) == "" ? 0 : trim($rec[6]))); 
    $rhSV = (!isset($rec[7]) ? 0 : (trim($rec[7]) == "" ? 0 : trim($rec[7]))); 
    $rhPV = (!isset($rec[8]) ? 0 : (trim($rec[8]) == "" ? 0 : trim($rec[8]))); 


        /* include('connect.php'); */
        set_time_limit(36000);
        ini_set('max_execution_time','43200');
        $e_results = mysql_query("SELECT ID FROM tbl_reading WHERE (READING_DATE = '".date("Y-m-d",strtotime($dDate))."' AND READING_TIME = '".date("H:i:s",strtotime($dTime))."') AND READING_ADDRESS = $address LIMIT 1"); 
        if(mysql_num_rows($e_results) <= 0 )
          if (!($dDate == 0 || $dTime == 0 || $address == 0) ) 
            if ($y == 0)
                $sql = "INSERT INTO tbl_reading (READING_DATE, READING_TIME, READING_ADDRESS, CO2_SET_VALUE, CO2_PROCESS_VALUE, TEMP_SET_VALUE, TEMP_PROCESS_VALUE, RH_SET_VALUE, RH_PROCESS_VALUE) VALUES ('".date("Y/m/d",strtotime($dDate))."','".date("H:i:s",strtotime($dTime))."', ". mysql_real_escape_string($address).",". mysql_real_escape_string($co2SV).",". mysql_real_escape_string($co2PV).",". mysql_real_escape_string($tempSV).",". mysql_real_escape_string($tempPV).",". mysql_real_escape_string($rhSV).",". mysql_real_escape_string($rhPV).")";
            
            else 
                $sql .= ", ('".date("Y/m/d",strtotime($dDate))."','".date("H:i:s",strtotime($dTime))."', ". mysql_real_escape_string($address).",". mysql_real_escape_string($co2SV).",". mysql_real_escape_string($co2PV).",". mysql_real_escape_string($tempSV).",". mysql_real_escape_string($tempPV).",". mysql_real_escape_string($rhSV).",". mysql_real_escape_string($rhPV).")";

            
           
          

            if(($x + 1) == $i)
                //echo ($x + 1)." = ".$i."<br>";
                if (substr($sql, 0, 1) == ",")
                    $sql = "INSERT INTO tbl_reading (READING_DATE, READING_TIME, READING_ADDRESS, CO2_SET_VALUE, CO2_PROCESS_VALUE, TEMP_SET_VALUE, TEMP_PROCESS_VALUE, RH_SET_VALUE, RH_PROCESS_VALUE) VALUES".substr($sql, 1);
                //echo $sql."<br>";
                set_time_limit(36000);
                try 

                    $result = mysql_query($sql) ;
                    $dCnt = mysql_affected_rows();
                    if( $dCnt  == 0)
                    
                        $errorDataCnt = $errorDataCnt + 1;
                    
                
                catch (Exception $e)
                
                    $conn->query("INSERT INTO tbl_log (LOG_DATE, DETAILS) VALUES ( NOW(), '".$e->getMessage()."' )");
                
                //mysql_free_result($result);
            

    unset($dDate); 
    unset($dTime); 
    unset($address); 
    unset($co2SV); 
    unset($co2PV); 
    unset($tempSV); 
    unset($tempPV); 
    unset($rhSV); 
    unset($rhPV);  



//function for looping into the records per line
function loop($data)

    $errorDataCnt = 0; $sql = ""; $exist = 0;
    $i = count( $data); $x = 0; $y = 0; $tmpAdd = ""; $cnt = 0; $t = 0; $dCnt = 0; 

    ini_set('max_execution_time','43200');
    while($x < $i) 
    
        $rec = explode(",", $data[$x]); 
        InsertData($rec, $errorDataCnt, $sql, $y, $i, $x, $dCnt);
        $x++; 
        $y++;
        unset($rec);
    

        $errFetch = ($i - $dCnt);
    if($errorDataCnt > 0)
        $conn->query("INSERT INTO tbl_log (LOG_DATE, DETAILS) VALUES ( NOW(), 'Error inserting $errFetch records. Check if there is a NULL or empty value or if it is the correct data type.' )");
    if($dCnt > 0)
        $conn->query("INSERT INTO tbl_log (LOG_DATE, DETAILS) VALUES ( NOW(), 'Saved $dCnt of $i records into the database. Total $exist records already existing in the database.' )");




// functions in looping records and passing into $contents variable
function DataLoop($file)

    ini_set("auto_detect_line_endings", true);
    set_time_limit(36000);
    ini_set('max_execution_time','43200');
    $contents = ''; $j = 0;
    if ($handle = fopen($file,"rb"))
        while (!feof($handle)) 
            $rdata = fgets($handle, 3359232);//filesize($file));
            //$rdata = fread($handle, filesize($file));
            if(trim($rdata) != "" || $rdata === FALSE)
                if (feof($handle)) break;
                else 
                $contents .= $rdata;
                $j = $j + 1; 
           
        fclose($handle);
        $data = explode("\n", $contents);
        unset($contents);
        unset($rdata);
    
    /* echo count($contents)." ".count($data); */
    /* $query = "SELECT MAX(`ID`) AS `max` FROM `tbl_reading`";
    $result = mysql_query($query) or die(mysql_error());
    $row = mysql_fetch_assoc($result);
    $max = $row['max']; */
    /* $res =   mysql_fetch_assoc(mysql_query("SELECT COUNT(*) as total FROM tbl_reading")) or die(mysql_error());
    echo "<script>alert('".$res['total']."')</script>"; */
    $p = 0;
    ini_set('memory_limit','512M');
    if($j != 0)
    
        foreach(array_chunk($data, ceil(count($data)/200)) as $rec_data)
            loop($rec_data);
            $p++;
        
     


【问题讨论】:

我已经尝试使用 PDO 逐一插入数据。我正在处理文本文件中的数十万行数据,这些数据必须以更好的性能有效传输。我在创建 PDO 批量插入时遇到困难,因为我想批量处理它。您可以访问我的第一个问题的链接以查看我的代码。 为您的餐桌显示SHOW CREATE TABLE CREATE TABLE tbl_reading (ID int(11) NOT NULL AUTO_INCREMENT, READING_DATE date DEFAULT NULL, READING_TIME time DEFAULT NULL, READING_ADDRESS int(11) DEFAULT NULL, @ 987654329@ 双默认空,CO2_PROCESS_VALUE 双默认空,TEMP_SET_VALUE 双默认空,TEMP_PROCESS_VALUE 双默认空,RH_SET_VALUE 双默认空,RH_PROCESS_VALUE 双默认空,isArchivetiny默认“0”,主键 (ID),) ENGINE=InnoDB AUTO_INCREMENT=611272 DEFAULT CHARSET=latin1 【参考方案1】:

您可以为此使用PDO::prepare。 http://php.net/manual/en/pdo.prepare.php

它是为这样的事情而设计的,应该更快一点(实际上并不是从经验中谈起)。只需用一些样本数据来衡量它。

$data = array(
     array(
         ':key1' => 'value1',
         ':key2' => 'value2',
     ),
     array(
         ':key1' => 'value3',
         ':key2' => 'value4',
     ),
);

$sql = 'INSERT INTO data_table (key1, key1) VALUES (:key1, key2);';
$stmt = $dbh->prepare($sql);
foreach($data AS $dataset) 
    $stmt->execute($dataset);

【讨论】:

我已经添加了我的代码。你能帮我批量插入吗?这样我就可以测试在批量插入或逐个插入之间哪个更有效。 我会将所有数据(作为数组)传递给 InsertData 方法,为插入查询创建一个语句(如示例中所示),然后遍历数组,准备数据并执行使用 $stmt->execute 进行查询。我不会做尝试的工作。试着玩一下,重写一些部分,如果你真的卡住了,那就再问一次。【参考方案2】:

这不是您运行查询(PDO、mysql、批量插入或其他)的方式,而是 InnoDB 引擎使插入速度太慢。 在开始插入之前,您需要做一些准备。 至于特定的插入语法 - 无关紧要。

在插入之前设置此选项

innodb_flush_log_at_trx_commit=0

或将您的所有插入操作放入一个事务中。 无论您选择什么语法或驱动程序,它都会非常快

【讨论】:

这是我的问题。我无法插入一笔交易。由于重复比较,进程挂起。

以上是关于在将多个或批量插入查询更改为 PDO 时需要帮助的主要内容,如果未能解决你的问题,请参考以下文章

使用 PDO 插入带有特殊字符的值

需要帮助以获取访问表单以将值插入查询

重复密钥更新时的 PDO 插入

访问VBA参数查询将整数更改为字符串

如何将Word中的嵌入式图片批量更改为非嵌入式?

PL / SQL触发器在更新或插入后更新同一个表