sql >> データベース >  >> RDS >> Mysql

200,00行の巨大なCSVファイルをMySQLにインポートする方法(非同期で高速)?

    この質問に答えてくれたすべての人に感謝します。私は解決策を発見しました!誰かが巨大なCSVファイルをMySQLデータベースにインポートするPHPスクリプトを作成する必要がある場合に備えて(非同期かつ高速に!)それを共有したかったのですが、40万行のコードをテストし、インポートが完了しました数秒で。大きなファイルでも機能すると思います。アップロードファイルの最大サイズを変更するだけです。

    この例では、2つの列(name、contact_number)を含むCSVファイルを同じ列を含むMySQLDBにインポートします。

    CSVファイルは次のようになります:

    アナ、0906123489

    ジョン、0908989199

    ピーター、0908298392

    ...

    ...

    だから、これが解決策です。

    まず、テーブルを作成します

    CREATE TABLE `testdb`.`table_test`
    ( `id` INT NOT NULL AUTO_INCREMENT ,
    `name` VARCHAR(100) NOT NULL ,
    `contact_number` VARCHAR(100) NOT NULL ,
    PRIMARY KEY (`id`)) ENGINE = InnoDB;
    

    次に、4つのPHPファイルがあります。あなたがしなければならないのは、これを単一のフォルダに置くことです。 PHPファイルは次のとおりです:

    index.php

    <form action="upload.php" method="post" enctype="multipart/form-data">
    <input type="file" name="csv" value="" />
    <input type="submit" name="submit" value="Save" /></form>
    

    connect.php

    <?php
    //modify your connections here
    $servername = "localhost";
    $username = "root";
    $password = "";
    $dbname = "testDB";
    $conn = new mysqli($servername, $username, $password, $dbname);
    if ($conn->connect_error) {
        die("Connection failed: " . $conn->connect_error);
    } 
    ?>
    

    senddata.php

    <?php
    include('connect.php');
    $data = $_POST['file'];
    $handle = fopen($data, "r");
    $test = file_get_contents($data);
    if ($handle) {
        $counter = 0;
        //instead of executing query one by one,
        //let us prepare 1 SQL query that will insert all values from the batch
        $sql ="INSERT INTO table_test(name,contact_number) VALUES ";
        while (($line = fgets($handle)) !== false) {
          $sql .= "($line),";
          $counter++;
        }
        $sql = substr($sql, 0, strlen($sql) - 1);
         if ($conn->query($sql) === TRUE) {
        } else {
         }
        fclose($handle);
    } else {  
    } 
    //unlink CSV file once already imported to DB to clear directory
    unlink($data);
    ?>
    

    upload.php

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.1/jquery.js"></script>
    <script>
    //Declaration of function that will insert data into database
     function senddata(filename){
            var file = filename;
            $.ajax({
                type: "POST",
                url: "senddata.php",
                data: {file},
                async: true,
                success: function(html){
                    $("#result").html(html);
                }
            })
            }
     </script>
    <?php
    $csv = array();
    $batchsize = 1000; //split huge CSV file by 1,000, you can modify this based on your needs
    if($_FILES['csv']['error'] == 0){
        $name = $_FILES['csv']['name'];
        $ext = strtolower(end(explode('.', $_FILES['csv']['name'])));
        $tmpName = $_FILES['csv']['tmp_name'];
        if($ext === 'csv'){ //check if uploaded file is of CSV format
            if(($handle = fopen($tmpName, 'r')) !== FALSE) {
                set_time_limit(0);
                $row = 0;
                while(($data = fgetcsv($handle)) !== FALSE) {
                    $col_count = count($data);
                    //splitting of CSV file :
                    if ($row % $batchsize == 0):
                        $file = fopen("minpoints$row.csv","w");
                    endif;
                    $csv[$row]['col1'] = $data[0];
                    $csv[$row]['col2'] = $data[1];
                    $min = $data[0];
                    $points = $data[1];
                    $json = "'$min', '$points'";
                    fwrite($file,$json.PHP_EOL);
                    //sending the splitted CSV files, batch by batch...
                    if ($row % $batchsize == 0):
                        echo "<script> senddata('minpoints$row.csv'); </script>";
                    endif;
                    $row++; 
                }
                fclose($file);
                fclose($handle);
            }
        }
        else
        {
            echo "Only CSV files are allowed.";
        }
        //alert once done.
        echo "<script> alert('CSV imported!') </script>";
    }
    ?>
    

    それでおしまい!複数の行を数秒でインポートできる純粋なPHPスクリプトがすでにあります。 :)(ajaxの使い方を教えてくれたパートナーに感謝します)



    1. UNION ALLは結果セットの順序を保証しますか?

    2. SQL Serverの既存のテーブルに主キーを追加する方法(T-SQLの例)

    3. PostgreSQLを使用して別のテーブルを更新するトリガーを挿入します

    4. 内部結合とin()句のパフォーマンスはどこですか?