将大数据文件导入MysQL的最佳方法

时间:2013-12-23 06:20:03

标签: php mysql

我有一个应用程序,它接收一个大小 16GB (大约 90,00,000行)的数据文件,该文件将被导入MySQL数据库。每次我运行php脚本时,即使数据库位于运行脚本的同一服务器上,我也会在查询期间收到错误'与MySQL服务器的连接

在互联网上搜索后,我发现当你耗尽一个资源进行数据库会话,,比如内存,而mysql关闭了连接时就会发生这种情况。想法就是交易你是运行时不应尝试插入大量数据。并且您可以通过将更高的值设置为“max_allowed_pa​​cket”来解决此问题。我在我的剧本中做到了这一点:

$db->query( 'SET @@global.max_allowed_packet = ' . 1 * 1024 * 1024 * 1024);

但这也不起作用。除非在插入明显更多行之后发生错误。'

现在,我将文件拆分为较小的文件,每个文件包含10,00,000行,然后处理每个文件。但即使分裂也需要相当长的时间。

我不是PHP程序员,也不是以前使用MySQL。这是别人的代码,我必须重构。所以我的知识几乎为零。

我正在使用LOAD DATA LOCAL INFILE语句来转储数据。是否有任何方法可以通过在每几行之后提交来缩短交易时间?

3 个答案:

答案 0 :(得分:2)

您确实需要使用BigDump

  

交错导入大型和非常大的MySQL Dump(如phpMyAdmin   2.x转储)即使通过具有硬运行时限制的Web服务器和处于安全模式的Web服务器也是如此。

配置它..请参阅herehere

答案 1 :(得分:0)

我编写了自己的转储脚本,基于与BigDump相同的行。这需要三个命令行争论:

  1. 要转储的全限定文件名
  2. 要转储的表
  3. 如果要提交事务,则加载了多少行。
  4.   

    <?php
        function GetCommaSeparatedValues($row) //Creates a comma separated list of all the column - values in the row
        {
            $str = '';
            $str =  '\'' . addslashes(substr($row,0,12)) . '\',' . //addslashes() escapes special characters with a '\' 
                    '\'' . addslashes(substr($row,12,12)) . '\',' .
                    '\'' . addslashes(substr($row,24,2)) . '\',' .
                    '\'' . addslashes(substr($row,26,24)) . '\',' .
                    '\'' . addslashes(substr($row,50,05)) . '\'';
            return str;
        }
    
        function print_error($err, $linenumber, $pk)
        {
            echo $err . ' at line number: ' . $linenumber . PHP_EOL;
        }
    
        ini_set('display_errors',1); 
        ini_set('display_startup_errors',1);
        error_reporting(E_ERROR); //Report only those errors that are fatal runtime errors
        ini_set('memory_limit', '-1'); //Allow script to use maximum available memory
        $query="";
        $totalqueries=$argv[3]; //Commit after loading how many lines
        $linenumber=0;
        $currenttotal=0;
        $handle = fopen($argv[1], "r"); //File to dump in database
        $tablename = $argv[2]; //table name of the db in which to dump file
    
        $con=mysqli_connect("db1","root","N3@k83@rd","pov2013p_pov");
    
        $lno = 0;
        $tempquery = 'SET @@global.max_allowed_packet = ' . 1 * 1024 * 1024 * 1024;
        mysqli_query($con,$tempquery);
        mysqli_autocommit($con,FALSE);
        if ($handle)
        {
                echo `date` . 'Importing file: ' . $argv[1] . PHP_EOL ;
                echo 'Commit after every '. $totalqueries . ' lines. ' . PHP_EOL;
                echo 'Dumping into table '. $tablename . PHP_EOL . PHP_EOL;
    
                while (($dumpline = fgets($handle)) !== false)
                {
                                                $lno++;
                        if($currenttotal == $totalqueries)
                        {
                                echo `date` . 'Commiting at line number: ' . $linenumber . PHP_EOL . PHP_EOL;
                                                                mysqli_commit($con);
                                $currenttotal=0;
                                if($temp)
                                {
                                        while(mysqli_next_result($con))
                                        {
                                                if($result = mysqli_store_result($con))
                                                {
                                                        while($r = mysqli_fetch_row($result))
                                                        {
                                                                echo('*');
                                                        }
                                                }
                                        }
                                }
    
                        }
                        $commaseparated = commaseparatedvalues($dumpline);
                        $query = 'INSERT INTO pov2013p_pov.'.$tablename.' VALUES ('. $commaseparated .');';
    
                        mysqli_query($con,$query) or print_error(mysqli_error($con),$lno,substr($dumpline,0,12));
                        $currenttotal++;
                        $linenumber++;
    
                }
                if($query!='')
                {
                        echo `date` . 'Commiting at line number: ' . $linenumber . PHP_EOL;
                        mysqli_commit($con);
                }
    
                echo `date` . 'Finished Import.' . PHP_EOL;
    
        }
        else
        {
                echo "Cannot open file";
        }
    ?>
    

答案 2 :(得分:-2)

以下是在命令行中导入的方法,您可以这样导入大文件:

mysql -hyourhostname-uusername -p databasename < yoursqlfile.sql