[英]PHP: best options to process csv files with a queue mechanism in order to make massive inserts on mysql database
[英]Optimize massive MySQL INSERTs
我有一個需要運行日常腳本的應用程序; 日常腳本包括下載具有1,000,000行的CSV文件,然后將這些行插入表格中。
我將應用程序托管在Dreamhost中。 我創建了一個while循環,該循環遍歷了CSV的所有行,並為每個循環執行INSERT查詢。 問題是我收到“ 500 Internal Server Error”。 即使我將其分成1000個文件(每個文件具有1000行),在同一循環中也不能插入40或5萬行以上。
有什么方法可以優化輸入? 我也在考慮使用專用服務器。 你怎么看?
謝謝!
佩德羅
大多數數據庫都有優化的大容量插入過程-MySQL的是LOAD DATA FILE語法 。
要加載CSV文件,請使用:
LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\r\n'
IGNORE 1 LINES;
插入多個值,而不是這樣做
insert into table values(1,2);
做
insert into table values (1,2),(2,3),(4,5);
一次最多可容納適當數量的行。
或執行批量導入,這是加載數據的最有效方式,請參閱
通常,我會說只使用LOAD DATA INFILE,但似乎您不能使用共享的托管環境。
我已經有好幾年沒有使用MySQL了,但是他們有一個很好的文檔,描述了如何加快批量插入的速度: http : //dev.mysql.com/doc/refman/5.0/en/insert-speed .html
可以從中得出一些想法:
禁用/啟用插入周圍的鍵:
ALTER TABLE tbl_name DISABLE KEYS; ALTER TABLE tbl_name啟用鍵;
在您的插入語句中使用許多值。
即:INSERT INTO表(col1,col2)值(val1,val2),(..,..),...
如果我沒記錯的話,每個插入語句最多可以有4096個值。
在開始之前,請運行FLUSH TABLES命令,以確保不存在任何可能影響插入性能的掛起磁盤寫操作。
我認為這將使事情變得更快。 我建議您使用LOCK TABLES,但是我認為禁用按鍵會引起爭議。
更新
閱讀此書后,我意識到,通過禁用密鑰,可以刪除對文件加載很重要的一致性檢查。 您可以通過以下方法解決此問題:
轉到phpmyadmin並選擇要插入的表。
在“操作”選項卡下,然后在“表選項”選項/ section下,將存儲引擎從InnoDB更改為MyISAM。
我曾經遇到過類似的挑戰。 玩的很開心。
您可以創建cronjob腳本,該腳本應一個請求將x個記錄添加到數據庫中。 Cronjob腳本將檢查最后一次導入是否未添加所有需要的行(他需要另外X行)。
因此,您可以添加所需數量的行。
如果您擁有專用服務器,它將更加容易。 您只需對所有插入查詢運行循環。
當然,您可以嘗試將time_limit設置為0(如果在Dreamhost上運行)或使其更大。
您的PHP腳本很可能已終止,因為它超出了腳本時間限制。 由於您位於共享主機上,因此您很不走運。
如果您確實切換到專用服務器並且可以訪問外殼程序,則最好的方法是使用mysql命令行工具插入數據。
OMG Ponies的建議很好,但我也已將數據“手動”格式化為mysqldump使用的相同格式,然后以這種方式加載。 非常快。
您是否嘗試過交易? 只需將命令BEGIN
發送到MySQL,完成所有插入操作,然后執行COMMIT
。 這樣可以大大加快速度,但是就像casablanca所說的那樣,您的腳本也可能會超時。
我自己之前曾遇到過這個問題,幾乎無法完全解決,但您需要做更多的工作才能使其表現最佳。
我發現在我的情況下,我無法接受一個大的INSERT語句,但是發現,如果像一次nos建議那樣一次將它分成大約10k個INSERTS組,它將很快完成工作。 需要注意的一件事是,當執行這樣的多個INSERT時,您很可能會達到PHP的超時限制,但是可以通過使用set_time_limit($ seconds)重置timout來避免這種情況,我發現在每次成功執行INSERT后都可以這樣做。
您必須謹慎執行此操作,因為您可能會因無限制的超時而陷入意外循環,為此,我建議您通過使用mysql_errno()檢查MySQL報告的錯誤來進行測試,以確保每個INSERT成功或mysql_error() 。 您還可以使用mysql_affected_rows()檢查受INSERT影響的行數來捕獲錯誤。 您可以在第一個錯誤發生后停止。
如果使用sqlloader會更好。 您將需要兩件事,第一件事是控制文件,該文件指定SQL Loader應該執行的操作,第二件事是要加載的csv文件。這是下面的鏈接,它可以為您提供幫助。 http://www.oracle-dba-online.com/sql_loader.htm
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.