2012-03-09 73 views
5

我有一個快速增長的寫入大量的PHP/MySql應用程序,它以每秒鐘大約十幾個的速度將新行插入數百萬行的INNODB表中。MySql INSERT vs PHP file_put_contents

我開始使用實時INSERT語句,然後移動到PHP的file_put_contents將條目寫入文件並將LOAD DATA INFILE寫入數據庫。哪種方法更好?

我應該考慮哪些方法?我怎麼能期望這兩種方法在將來處理衝突和增加負荷?

謝謝!

+0

一種替代方法是寫入輔助表,然後在主表上寫入主表時遇到問題,然後在主表上寫入'insert into ... select from'到主表。 – 2012-03-09 18:52:11

回答

3

認爲LOAD DATA INFILE是插入數據的批處理方法。它消除了爲每個語句啓動插入查詢的開銷,因此速度更快。但是,處理錯誤時會失去一些控制權。處理單個插入查詢中的錯誤比文件中間的一行更容易。

+0

您可以使用語法insert into表值(row1),(row2),...,(rowN);通過單個查詢插入儘可能多的行。你也可以附加「... on duplicate key update ...」來指定如何處理唯一的鍵衝突 – atxdba 2012-03-10 00:40:01

+0

@atxdba這對大插入是一個可怕的想法。 – feketegy 2012-03-10 08:03:22

+0

@feketegy可怕的如何?性能? http://tinyurl.com/7jmzbcp是SO貼出瞭如何更好和更喜歡。當然,你不想在一次插入中加載幾個數據集,但是做一個毛毯未定義的聲明,它是可怕的,這是完全錯誤的。即使mysqldump默認會創建批量插入。如果你說的是大量的數據加載數據可能會更好,我不會爭辯說。我真的只是指出可用的語法。 – atxdba 2012-03-10 17:21:09

0

我們處理插入的方式是讓它們發送到像ActiveMQ這樣的消息隊列系統。從那裏我們有一個單獨的應用程序,它使用LOAD DATA INFILE以大約5000的批量加載插入。錯誤處理仍然可以通過infile進行,但是它可以更快地處理插入。如果設置消息隊列超出了應用程序的範圍,那麼沒有理由認爲file_put_contents不是一個可接受的選項 - 特別是如果已經實現並且工作正常。

此外,您可能希望在寫入期間測試禁用索引以查看是否可以提高性能。

+0

關於禁用索引的好消息 - 謝謝 – user1259956 2012-03-09 19:16:35

+0

需要考慮的另一點是你的特定系統的瓶頸在哪裏。嘗試使用iostat和vmstat來確定你的放慢速度以及你應該在哪裏集中精力。根據您對數據的處理方式,有許多存儲解決方案,如果不是ACID友好的,其中一些解決方案的速度會更快。 – RumpRanger 2012-03-09 19:56:16

0

聽起來你不應該使用innoDB。無論如何,即使對於蹩腳的硬件,每秒鐘也不會有問題,除非可能您的數據模型非常複雜,但爲此,LOAD DATA INFILE非常好,因爲它只重建一次索引,而不是每個插入。所以使用文件是一個體面的方法,但確保你打開它們只能追加模式。從長遠來看(1k +寫/秒),查看其他數據庫 - 特別是cassandra以編寫大量應用程序。

+0

索引也在我的腦海裏。每寫入哪個版本會更快 - 附加到平面文件或插入到數據庫中?他們將如何處理併發請求? – user1259956 2012-03-09 19:14:56

+0

這真的取決於,你需要運行測試併爲你的環境弄清楚。如果你將數據限制在一個限制範圍內(我相信它在Linux上是4K),那麼附加到一個文件是唯一的原因,否則你會遇到併發問題 – miki 2012-03-09 19:26:07

2

取決於您是否可以負擔讓PHP插入的數據不能立即在表中可用,那麼INSERT DELAYED可能是一個選項。

MySQL將接受要插入的數據,稍後將處理插入,並將其放入隊列中。所以這不會阻止你的PHP應用程序,而MySQL會確保稍後插入數據。

As it says in the manual:

使用INSERT DELAYED的另一個主要好處是從很多客戶插入被捆綁在一起,並寫在一個塊。這比執行許多單獨的插入要快得多。

我已經使用這個用於記錄數據,其中數據丟失是不是致命的,但如果你希望從服務器崩潰時保護從INSERT DELAYED數據都尚未插入,你可以看看複製的變化而去一個專用的奴隸機器。

0

如果您確實要執行sql插入路由,請在事務中包裝pdo execute語句。這樣做會大大加快這一進程。