2012-12-27 51 views
1

我正在開發基於Symfony 2的項目,需要使用cron任務定期從.csv文檔導入150萬個產品。在Symfony 2中導入大型數據集

進口目前看起來是這樣的:

... 

    Propel::disableInstancePooling(); 

    $fp = fopen($file, 'r'); 
    while (!feof($fp)) { 
     $line = fgets($fp, 2048); 
     $data = str_getcsv($line, "\t"); 

     $product = new Product(); 
     $product->setId($data[0]); 
     $product->setTitle($data[1]); 
     ... 
     $product->save(); 
    } 

    ... 

約5分鐘後然而阿帕奇達到其512MB的內存分配,並引發以下錯誤:

Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 78 bytes) in /var/www/vhosts/myapp.local/app/cache/dev/classes.php on line 9451

我已禁用的Propel的實例池(這在以前Propel在其他框架中支持導入過程中工作過),問題仍然存在,所以我想知道Symfony 2是否正在執行任何類型的緩存(基於錯誤存在拋出)。

有沒有人在Symfony 2中執行大量進口的任何經驗可以讓我指出正確的方向?

回答

1

實際上,這個導入應該直接在mysql層次上完成(mysql可以從csv文件讀取數據),除非它非常複雜。另一種方法是逐步讀取文件,生成一個sql文件並在原生文件之後將其導入數據庫。 Web應用程序直接處理這種大型導入沒有理由,因爲您的內存不足。

確保您不會一次將整個csv加載到內存中。

其他解決方案是給php.ini更多的內存,並希望最好的。 Php不是批量處理大量數據的最佳語言。

+0

好吧,我將看看在MySQL級別導入它。這種數據導入的大小對我來說是新的領域。您理所當然地提到,PHP不是針對此級別的數據進行修補程序的最佳語言。你會建議我看看Python作爲替代嗎?謝謝。 –

+0

這取決於。只要你預處理數據(如果你沒有像mysql的sql語句那樣以本地格式接收它),並且你在資源消耗方面非常小心(所以你沒有耗盡內存),你可以將數據轉換成一種mysql可以理解的格式。一種方法是從文件中讀取前x行,將生成的sqls轉儲到文件中。繼續閱讀,直到完成整個文件。一旦你有了sql,讓mysql客戶端做它的工作。它會比你做的更快。但要小心,測試你的腳本。由於腳本不佳,我看到數據丟失太多。 – Xnoise

+0

老實說,我不知道如果python更好,或c更好,或任何其他語言。你只需要注意資源並明智地使用它們。 MySQL客戶端會最多做其餘的事情。 – Xnoise

1

哦,男孩,我在那裏就像6個月前,對你來說一句話:交易。

切的CSV的作品,如在10000行或多或少和執行每包1周的交易,這樣你可以避免寫150萬次,以分貝的開銷,並寫像150

。希望指導你一個很好的解決方案,我無法將時間從30秒縮短,也許你應該考慮一個離線任務處理器來處理這些類型的io/cpu綁定任務。

目前,此頁面是我的聖經: http://propelorm.org/documentation/06-transactions.html

編輯

其實我認爲這是某種形式的導入動作由現場需要,如果它是一個一次性的事情,你「開發商「需要做我會與Xnoise建議。

+0

謝謝您的回覆。我正在考慮用C#編寫一些東西來離線處理,但理想情況下,我需要每兩到三天運行一次,並希望避免手動處理數據的麻煩。 –

+2

Python會做到這一點,沒有太多的麻煩,csv模塊很好,檢查了這一點。 http://stackoverflow.com/questions/10154633/load-csv-data-into-mysql-in-python –