簡體   English   中英

增強csv文件數據庫導入

[英]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.

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