簡體   English   中英

將大型CSV文件導入MySQL

[英]Import Large CSV file into MySQL

我正在嘗試將一個csv文件導入到一個mysql表中,我目前有一個逐行運行的腳本,因為我需要將一個id與另一個id結合使用以及格式化mysql格式的日期。

csv文件的列數多於我當前導入的列數。 是否更容易導入所有列?

我正在閱讀LOAD DATA INFILE(http://dev.mysql.com/doc/refman/5.1/en/load-data.html),但我想知道如何使用它並散列id並格式化日期沒有逐行執行。 我當前的腳本占用時間太長,導致運行時出現站點性能問題。

這是我有的:

$url = 'http://www.example.com/directory/file.csv';
if (($handle = fopen($url, "r")) !== FALSE) 
{
fgetcsv($handle, 1000, ",");
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) 
{
    $EvID = $data[0];
    $Ev = $data[1];
    $PerID = $data[2];
    $Per = $data[3];
    $VName = $data[4];
    $VID = $data[5];
    $VSA = $data[6];
    $DateTime = $data[7];
    $PCatID = $data[8];
    $PCat = $data[9];
    $CCatID = $data[10];
    $CCat = $data[11];
    $GCatID = $data[12];
    $GCat = $data[13];
    $City = $data[14];
    $State = $data[15];
    $StateID = $data[16];
    $Country = $data[17];
    $CountryID = $data[18];
    $Zip = $data[19];
    $TYN = $data[20];
    $IMAGEURL = $data[21];
    $URLLink = $data[22];

        $data[7] = strtotime($data[7]);
        $data[7] = date("Y-m-d H:i:s",$data[7]);

    if((($PCatID == '2') && (($CountryID == '217') or ($CountryID == '38'))) || (($GCatID == '16') or ($GCatID == '19') or ($GCatID == '30') or ($GCatID == '32'))) 
    {
            if(!mysql_query("INSERT IGNORE INTO TNDB_CSV2 
                (id, EvID, Event, PerID, Per, VName,
                     VID, VSA, DateTime, PCatID, PCat,                
                CCatID, CCat, GCatID, GCat, City,
                     State, StateID, Country, CountryID, Zip,
                TYN, IMAGEURL) VALUES
                ('".md5($EventID.$PerformerID)."','".addslashes($data[0])."','".addslashes($data[1])."','".addslashes($data[2])."','".addslashes($data[3])."','".addslashes($data[4])."',
                    '".addslashes($data[5])."','".addslashes($data[6])."','".addslashes($data[7])."','".addslashes($data[8])."','".addslashes($data[9])."',
                '".addslashes($data[10])."','".addslashes($data[11])."','".addslashes($data[12])."','".addslashes($data[13])."','".addslashes($data[14])."',
                    '".addslashes($data[15])."','".addslashes($data[16])."','".addslashes($data[17])."','".addslashes($data[18])."','".addslashes($data[19])."',
                '".addslashes($data[20])."','".addslashes($data[21])."')"))
            {                    
                exit("<br>" . mysql_error());
            }
    }
}
fclose($handle);
}

任何幫助總是非常感謝。 提前致謝。

首先嘗試優化腳本。 首先,除非您沒有其他選擇,否則在導入時永遠不會運行單個查詢,網絡開銷可能是一個殺手。

嘗試類似的東西(顯然在SO文本框中未經測試和編碼,檢查括號匹配等):

$url = 'http://www.example.com/directory/file.csv';
if (($handle = fopen($url, "r")) !== FALSE) 
{
fgetcsv($handle, 1000, ",");

$imports = array();

while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) 
{
    $EvID = $data[0];
    $Ev = $data[1];
    $PerID = $data[2];
    $Per = $data[3];
    $VName = $data[4];
    $VID = $data[5];
    $VSA = $data[6];
    $DateTime = $data[7];
    $PCatID = $data[8];
    $PCat = $data[9];
    $CCatID = $data[10];
    $CCat = $data[11];
    $GCatID = $data[12];
    $GCat = $data[13];
    $City = $data[14];
    $State = $data[15];
    $StateID = $data[16];
    $Country = $data[17];
    $CountryID = $data[18];
    $Zip = $data[19];
    $TYN = $data[20];
    $IMAGEURL = $data[21];
    $URLLink = $data[22];

        $data[7] = strtotime($data[7]);
        $data[7] = date("Y-m-d H:i:s",$data[7]);

    if((($PCatID == '2') && (($CountryID == '217') or ($CountryID == '38'))) || (($GCatID == '16') or ($GCatID == '19') or ($GCatID == '30') or ($GCatID == '32'))) 
    {

    $imports[] = "('".md5($EventID.$PerformerID)."','".addslashes($data[0])."','".addslashes($data[1])."','".addslashes($data[2])."','".addslashes($data[3])."','".addslashes($data[4])."',
                    '".addslashes($data[5])."','".addslashes($data[6])."','".addslashes($data[7])."','".addslashes($data[8])."','".addslashes($data[9])."',
                '".addslashes($data[10])."','".addslashes($data[11])."','".addslashes($data[12])."','".addslashes($data[13])."','".addslashes($data[14])."',
                    '".addslashes($data[15])."','".addslashes($data[16])."','".addslashes($data[17])."','".addslashes($data[18])."','".addslashes($data[19])."',
                '".addslashes($data[20])."','".addslashes($data[21])."')";



    }
}

$importarrays = array_chunk($imports, 100);
foreach($importarrays as $arr) {

 if(!mysql_query("INSERT IGNORE INTO TNDB_CSV2 
                (id, EvID, Event, PerID, Per, VName,
                     VID, VSA, DateTime, PCatID, PCat,                
                CCatID, CCat, GCatID, GCat, City,
                     State, StateID, Country, CountryID, Zip,
                TYN, IMAGEURL) VALUES ".implode(',', $arr)){

     die("error: ".mysql_error());

 }

 }

fclose($handle);
}

使用array_chunk中的數字,太大,可能會導致查詢太長等問題(是的,my.cnf中存在可配置的限制),太小而且不必要的開銷。

你也可以放棄使用$ data [x]給變量作為浪費,因為腳本有多小,只需在你的查詢中直接使用$ data [x](不會給出大的改進,但取決於你的進口大小可以節省一點)。

接下來將使用低優先級插入/更新,請查看此信息以獲取更多信息以幫助您入門: 如何優先處理某些查詢?

畢竟,你可以想到mysql配置優化,但這是一個谷歌解釋真的,因為最好的設置是不同的每個人和他們獨特的情況

編輯:我之前做過的另一件事是,如果您設置了很多導入不需要的密鑰,您可以暫時刪除這些密鑰,並在腳本完成后將其添加回來。 這也可以帶來很好的時間改進,但是當你在一個實時數據庫上工作時,如果沿着這條路走下去,就會有一些陷阱。

嘗試使用implode()函數進行批量插入。 有關進一步說明和示例,請參閱此線程通過php數組將多行插入mysql

我用過這個查詢

$sql = "
        LOAD DATA LOCAL INFILE 'uploads/{$fileName}'
        REPLACE INTO TABLE `order`
        FIELDS
            TERMINATED BY '\t'
        LINES
            TERMINATED BY '\r\n'
        IGNORE 1 LINES
        (product_id, `date`, quantity)
        ";

它超級快

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM