簡體   English   中英

在mysql數據庫中存儲大文件/二進制數據:什么時候可以嗎?

[英]Storing large files / binary data in a mysql database: when is it ok?

好的,我已經搜索了這個,並閱讀了關於在[MySQL]數據庫中存儲二進制數據的幾點觀點。 一般來說,我認為這是一個壞主意,並試圖避免它,支持傳統的文件傳輸,只是在數據庫中存儲對文件的引用。

但是,我正在開發一個項目,該項目需要與遠程/雲數據庫進行數據庫同步,不僅適用於文件,還適用於設置和其他用戶內容。 出於這個原因和其他原因,我覺得這可能是數據庫中二進制存儲的合適情況。

我已經為數據庫同步編寫了一個通用系統,它可以很好地使用Reflection和XML。 我也(以我的直覺)將文件存儲集成到這個系統中。 再次,它運行良好 - 我將文件切換到64Kb BLOB並將它們存儲在一個表中,帶有file_id引用(鏈接到一個單獨的表,其中包含元數據,如文件名/大小/ mime類型)。

這使我能夠在連接可用時發送碎片,並允許我限制每個請求大小以保持平穩運行。

到目前為止,我還沒有發現任何問題,並已成功導入和傳輸超過1GB的數據(超過10-15個文件/ 16000行),但我擔心它的可擴展性 - 一旦有了它會減慢20gb +數據在那里,或者MySQL可以處理它,只要我的查詢結構良好?

我決定將數據存儲在數據庫中的另一個原因是,我認為如果空間不足,我可以簡單地向MySQL添加另一個HDD /存儲設備,以期有效擴展/復制/等。

我非常感謝任何觀點或評論是關於這是一個好的還是壞的方法,並且我錯過了我曾經在生產環境中使用過的任何明顯的問題?

編輯:我忘了提一下,文件大小可以從1KB到1GB不等

[粗略]結論首先:非常感謝那些提出深思熟慮的答案的人。 在這里選擇接受的答案非常困難,因為每個人都有一些體面的東西可供選擇。

最后(盡管我的希望),我已經決定純粹的MySQL存儲服務器充其量只是一個好的解決方案(我仍然不禁想知道為什么他們打擾包括BLOB類型)。

作為替代方案,我在@Nick Coons文件系統方法和@ tadman使用輕量級鍵/值數據庫引擎(如leveldb)的混合建議之間徘徊。 如果在這個項目中使用leveldb的實用性不是問題,這很可能是我將努力的方法。

我已經在此基礎上接受了tadman的回答; 他的回答對我的情況也是最適用和有用的。

話雖如此,對於那些感興趣的人:到目前為止,我只使用MySQL獲得了很多成功。 我已經測試了一個存儲超過15gb二進制數據的表,沒有任何明顯的負面影響,從大表中插入/檢索數據(仔細查詢)。 但是,我確信這仍然是非常低效的,所提到的任何替代方法都會明顯更好。

簡答:

我不確定是否有一種強硬的方式來回答這個問題。 你提到的文件從1KB到1GB。我不會在數據庫中存儲二進制數據,如果它接近1KB,那就是1GB。 如果它是偶然的,我可以在DB中存儲幾個字節的二進制數據,但是任何大量的數據,特別是不需要搜索的數據,都應該存儲在文件系統中:

當您將數據存儲在數據庫中時,無論如何都要將其存儲在文件系統中,您只需添加另一層(數據庫)即可。 這一層需要付出代價,因此彌補差異應該是有益的。 如果您要存儲數據以便可以根據它進行搜索或將其加入其他數據,那么這是有道理的。 但是文件數據(二進制或不二進制)通常不以這種方式使用。

示例實施:

有更好的方法來分發文件數據,而不是將其輸入數據庫,例如分布式文件系統(檢查GlusterFS,MooseFS,這兩種方法都可以通過簡單地添加額外的硬盤來擴展,而MySQL則不會。)

通常,我會使用數據的SHA1哈希值將文件數據存儲在文件系統中作為文件的名稱。 如果哈希是98a75af529f07b1ef7be7400f51344b9f07b1ef7,那么我將它存儲在這個目錄結構中:

./98/a7/98a75af529f07b1ef7be7400f51344b9f07b1ef7

也就是說,一個由前兩個字符組成的頂級目錄,一個由后兩個字符組成的二級目錄,最后是一個名稱為總字符串的文件。 通過這種方式,我可以真正擁有數十億個文件而不會在一個目錄中擁有太多的文件,系統運行速度太慢。

然后我創建一個包含這些列的數據庫表來保存元數據:

  • file_id,auto_increment字段
  • created,一個默認值為current_timestamp的字段
  • prev_id,更多內容如下
  • hash,文件系統上的SHA1哈希
  • name,文件的文本名稱(例如文件在磁盤上的原始名稱。

當我需要分層目錄結構時,我還會創建一個目錄表並將dir_id添加到上面的列列表中。

如果我編輯./98/a7/98a75af529f07b1ef7be7400f51344b9f07b1ef7表示的文件,我實際上並沒有在磁盤上更改該文件,我創建了一個新文件(因為新文件內容將由新的SHA1哈希表示),並創建一個files文件表中的新條目,其中prev_id等於我編輯的文件的file_id。 換句話說,我現在有版本控制。

如果我需要以分布式方式提供,我設置MySQL復制,然后使用GlusterFS在多個服務器上復制他的文件系統。

我不得不想知道為什么你甚至對數據庫感到煩惱,當你在chunk,store,retrieve和reassemble上添加的層在一個明確定義的文件系統結構上也能正常工作時。 MySQL的希望所有的單個卷上的數據,所以每當你覺得它是不加其它驅動器的情況下,以及大量的二進制數據的復制將是幾近極限的緩慢,因為二進制日志最終會復制量您需要存儲的數據。

最簡單的方法通常是最好的方法。 直接在文件系統中存儲它可能是最好的方法。 如果你需要保存存儲在哪里的索引,也許你會使用像MySQL這樣的數據庫,但是有很多方法可以完成同樣的任務。 技術越低越好。 例如,不要排除SQLite,因為嵌入式數據庫在輕度讀寫加載下表現良好,並且在備份和恢復方面具有“僅僅是文件”的優勢。

話雖這么說,你所做的事聽起來與LevelDB相似,所以在你采用你的方法之前,你必須看到它與這種類型的鍵值文檔存儲有很大不同。

我想你會在我開始研究這個問題時找到相當多的辯論。 我傾向於傾向於存儲在文件系統中並維護引用。 但是,這並不是說從來沒有時間將二進制數據存儲在數據庫中。

我想說,只是為了保持同步,本身並不是為了在數據庫中存儲二進制數據的論據。 當然有辦法使文件系統保持同步,以便數據庫保持同步,因此文件系統也是如此。

最重要的是,關於這個話題存在相當多的爭論,你必須選擇適合你的方法。 如果你設置了什么工作。 用它。 進行性能和負載測試以確保其正常工作。 如果它沒有阻止,請更改它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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