今天一朋友遇到將excel數(shù)據(jù)導(dǎo)入到mysql數(shù)據(jù)庫, 20多萬條的數(shù)據(jù)導(dǎo)入到mysql需要兩分多鐘,老板認(rèn)為這個(gè)速度太慢了,于是我們就一起想辦法,最終把時(shí)間縮短到13秒左右, 這里把解決問題的經(jīng)過給大家做個(gè)分享.
兩分鐘是這樣的: 用phpexcel讀取文件,然后通過foreach循環(huán)使用tp的插入數(shù)據(jù)庫方法
測(cè)試1,讀取phpexcel, 然后做個(gè)循環(huán),不插入數(shù)據(jù)庫就需要 1分多鐘,于是就意識(shí)到讀取 excel太花時(shí)間,那么有沒有更好的文件可以讀取呢
測(cè)試2, 通過搜索,可以通過PHP直接讀取csv格式的文件,于是,換成 csv的文件讀取,時(shí)間少了一半,但仍然覺得時(shí)間太久
測(cè)試3, tp插入數(shù)據(jù)庫的方法比較花時(shí)間,然后換成原來 php連接插入數(shù)據(jù)庫, 時(shí)間再次所短一半,這個(gè)時(shí)候還需要 30 多秒,能不能再減少了
測(cè)試4, 思考:既然循環(huán)需要時(shí)間,那么是否可以大批量插入呢,經(jīng)過搜索,原來sql語句還可以這樣寫:
INSERT table_name (column1, column2, ..., columnN) VALUES (rec1_val1, rec1_val2, ..., rec1_valN), (rec2_val1, rec2_val2, ..., rec2_valN), ... ... (recM_val1, recM_val2, ..., recM_valN); 這里可以寫多行喲,我寫了1萬行,沒有問題
測(cè)試5, 把20多萬分成20多次分批導(dǎo)入,時(shí)間再次縮短了很多,最終 13秒 搞定[本人電腦配置一般,電腦好應(yīng)該會(huì)再快一些]
代碼如下:
$filepath = EXTEND_PATH."ccc.csv";
$dsn = "mysql:host=localhost;dbname=aftts";
$db = new \PDO($dsn, 'root', 'root'); //PHP Data Object
$db->exec("SET names 'utf8'");//保證數(shù)據(jù)庫添加不出現(xiàn)亂碼
$start = time();
//csv 導(dǎo)入數(shù)據(jù)開始
$file = fopen($filepath,'r');
$data = fgetcsv($file);
$sql = "INSERT INTO tp_test (a, b,c,d,e,f,g) VALUES";
$s = "";
$i=1;
while ($data = fgetcsv($file)) {
//每次讀取CSV里面的一行內(nèi)容
$a = $data[0];
$b = $data[1];
$c = iconv('gb2312','utf-8',$data[2]);
//中文轉(zhuǎn)碼,否則亂碼 或者 mb_convert_encoding($data[0],'utf-8','gbk');
$d = $data[3];
$e = iconv('gb2312','utf-8',$data[4]);
$f = $data[5];
$g = iconv('gb2312','utf-8',$data[6]);
if($<10000)//一次性給數(shù)據(jù)庫過大,數(shù)據(jù)庫受不了的
{ $s .= "('$a','$b','$c','$d','$e','$f','$g'),";}
else{
$dd[] = $sql . substr($s,0,strlen($s)-1);
$s = "('$a','$b','$c','$d','$e','$f','$g'),";
$i = 1;
}
$i++;
}
if($i<10000){
$dd[] = $sql . substr($s,0,strlen($s)-1);
}
foreach ($dd as $sql) {
$db->exec($sql);
}
注意, 如果遇到下面的格式, 導(dǎo)入可能會(huì)有問題, 這個(gè)時(shí)候需要先在csv文件里面轉(zhuǎn)換一下格式