[英]Enhance csv file database import
我正在使用以下腳本將大型csv文件導入到我的數據庫中。
如果表為空,則此過程大約需要5分鍾才能在本地計算機上完成。
如果我正在使用文件更新同一表上的現有值,則需要15分鍾以上才能完成。
我的csv文件包含大約35,000行。
我如何加快這一過程?
if ( $request->get( $_POST["action"] ) == "import" ) {
$file = $upload->file_upload( "import", "media/import" );
if ( file_exists( DIR_UPLOAD_PHOTO . "/media/import/" . $file ) ) {
$file = DIR_UPLOAD_PHOTO . "/media/import/" . $file;
$handle = fopen( $file, "r" );
if ( $handle ) {
$lines = explode( "\r", fread( $handle, filesize( $file ) ) );
}
$total_array = count( $array );
$x = 0;
foreach ( $lines as $line ) {
if ( $x >= 1 ) {
$data = explode( "|", $line );
$titlu = trim( addslashes( $data[0] ) );
$alias = $this->generate_seo_link( $titlu );
$gramaj = trim( $data[1] );
$greutate = trim( $data[2] );
$pret_total = trim( $data[3] );
$pret_redus = trim( $data[4] );
$poza = trim( $data[5] );
$pret_unitar = trim( $data[6] );
$categorie = trim( $data[7] );
$brand = trim( addslashes( $data[8] ) );
$descriere = trim( addslashes( $data[9] ) );
$vizibil = trim( $data[10] );
$cod = trim( $data[11] );
$nou = trim( $data[12] );
$cant_variabila = trim( $data[13] );
$congelat = trim( $data[14] );
$tva = trim( $data[15] );
$stoc = trim( $data[16] );
if ( $cod != "" && $cod != " " ) {
$verificare = $database->select( "SELECT alias FROM produse WHERE alias LIKE '%" . $alias . "%'" );
for ( $i = 0; $i < $database->countRows(); $i++ ) {
if ( $alias == $verificare['alias'][$i] ) {
$alias = $this->increment_string( $alias, '_', 1 );
} else {
$alias = $alias;
}
}
$database->insert( sprintf( "insert into produse set
titlu='%s',
alias='%s',
gramaj='%s',
greutate='%s',
prettotal='%s',
pretredus='%s',
poza='%s',
pretunitar='%s',
categorie='%d',
brand='%s',
descriere='%s',
vizibil='%d',
cod='%s',
nou='%d',
cant_variabila='%d',
congelat = '%d',
tva = '%s',
stoc = '%d'
on duplicate key update
titlu='%s',
gramaj='%s',
greutate='%s',
prettotal='%s',
pretredus='%s',
poza='%s',
pretunitar='%s',
categorie='%d',
brand='%s',
descriere='%s',
vizibil='%d',
cod='%s',
nou='%d',
cant_variabila='%d',
congelat = '%d',
tva='%s',
stoc= '%d'",
$titlu, $alias,
$gramaj, $greutate, $pret_total, $pret_redus, $poza, $pret_unitar, $categorie,
$brand, $descriere, $vizibil, $cod, $nou, $cant_variabila, $congelat,
$tva, $stoc,
$titlu, $gramaj, $greutate,
$pret_total, $pret_redus, $poza, $pret_unitar, $categorie, $brand, $descriere,
$vizibil, $cod, $nou, $cant_variabila, $congelat, $tva, $stoc ) );
}
}
$x++;
}
}
}
這是我的增量功能
function increment_string($str, $separator = '-', $first = 1){
preg_match('/(.+)'.$separator.'([0-9]+)$/', $str, $match);
return isset($match[2]) ? $match[1].$separator.($match[2] + 1) : $str.$separator.$first;
}
首先,您做的越少-速度越快。 但是,由於硬盤驅動器,許多數據庫導入都很慢。 不是因為CPU,不是因為RAM不足-這是硬盤驅動器。
原因如下:硬盤以每秒輸入輸出操作的速度運行 -我將其稱為I / O。 那是制造商不做廣告的數字。 他們宣傳諸如bandband和burst read之類的東西,這些東西大多是無用的數字,例如鼠標的DPI。
機械磁盤的可用I / O數量相對較少。 該數字取決於驅動器,它可以是100到400個I / O之間的任何值。 SSD具有更多可用的I / O,數量從5000到80k(甚至更多)。
這意味着機械磁盤可以在1秒內執行400次寫入,而SSD可以進行5000次寫入。問題在於數據庫查詢通常在數據方面很小(大約4KB)。
如果您做簡單的數學運算-400 I / O * 4KB-您得到的數字約為1.6 MB /秒。 這表明您正在花費所有I / O,但浪費了磁盤帶寬的所有容量。
這也暗示您可以為每個I / O發出更大的數據寫操作。 用凡人語言,它只是意味着您應該啟動一個事務,發出多個INSERT查詢(例如50個INSERT),然后提交該事務。
這樣,您花費了1個I / O進行了50次插入操作。 反過來,它實際上快了50倍。 如果使用准備好的語句,這將變得更加高效,因為MySQL不必在每次發送查詢時都對查詢進行lex處理。
我不會發送任何代碼,因為您應該能夠自行修復它。 另外,您的代碼也可以進行SQL注入。 您需要修改一些內容,如果不確定什么是准備好的語句,請大聲喊叫。
將SELECT推入INSERT,以便它們都在服務器上運行,而不是從客戶端到服務器來回移動。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.