2009-11-11 45 views
10

我正在努力決定是否應該在即將推出的項目中使用MySQL blob字段類型。我應該使用MySQL blob字段類型嗎?

我的基本要求是,會有某些數據庫記錄可以查看,並有多個文件上傳並「附加」到這些記錄。看到上述記錄可能僅限於某些人的具體情況。任何類型的文件都可以上傳,幾乎沒有限制。因此,從一種方式來看,如果我使用MySQL路由,我不必擔心病毒的蔓延或隨機的php文件上傳並以某種方式執行。我還有一個更容易獲得許可並保持數據接近記錄的路徑。

另一個明顯的路線是將數據存儲在webroot之外的特定文件夾結構中。在這種情況下,我不得不想出一個特殊的文件夾/文件命名約定來跟蹤他們在數據庫中引用的內容。

使用MySQL blob字段類型時性能是否受到影響?我擔心選擇阻礙網站未來發展的解決方案,以及選擇不易維護的解決方案。

回答

10

如果您的網絡服務器將通過網絡提供這些上傳的文件,那麼如果它們存儲在文件系統中,性能幾乎肯定會更好。然後,Web服務器將能夠應用HTTP緩存提示,如Last-ModifiedETag,這將有助於用戶多次訪問同一文件的性能。此外,網絡服務器將在服務時自動爲該文件設置正確的Content-Type。如果您將數據庫存儲在數據庫中,那麼當您從Web服務器上免費獲得它們時,您最終將實現上述功能以及更多功能。

此外,從您的數據庫中提取大量blob數據可能最終成爲數據庫性能瓶頸。另外,您的數據庫備份可能會比較慢,因爲它們將備份更多數據。如果您在開發過程中正在進行臨時查詢,那麼在結果集中查看select語句的大塊會很不方便。如果你想簡單地檢查一個上傳的文件,這將是不方便和迂迴的,因爲它會被尷尬地存儲在數據庫列中。

我會堅持將文件存儲在文件系統和數據庫中文件路徑的常見做法。

2

大量數據最終會影響性能。 MS SQL 2008是在文件系統中存儲二進制數據的專用方式:

http://msdn.microsoft.com/en-us/library/cc949109.aspx

我會採用類似的方法也爲您的項目了。

您可以創建一個FILES表來保存關於文件的信息,例如原始名稱。要安全地將文件存儲在磁盤上,請使用GUID進行重命名。將新文件名存儲在FILES表中,當用戶需要下載時,您可以在磁盤上輕鬆找到並將其傳送給用戶。

0

在我看來,在數據庫中存儲文件是個壞主意。你可以在那裏存儲的是id,name,type,可能是文件的md5散列,以及插入的日期。文件可以上傳到公共場所以外的文件夾中。此外,您應該擔心不建議將1000個以上的文件保存在一個文件夾中。因此,每次文件ID增加1000時,您必須創建新文件夾。

9

使用MySQL blob字段類型時性能是否受到影響?

不是固有的,但如果你有大的BLOB堵塞你的表和內存緩存,肯定會導致性能下降。

另一個顯而易見的途徑是將數據存儲在webroot之外的特定文件夾結構中。在這種情況下,我不得不想出一個特殊的文件夾/文件命名約定來跟蹤他們在數據庫中引用的內容。

是的,這是一種常用的方法。你通常會做一些類似文件夾的命名,這些文件夾與每個關聯的表格命名,其中包含僅基於主鍵的文件名(理想情況下是一個整數;絕對不會有用戶提交的任何內容)。

這是一個更好的主意嗎?這取決於。只有一個數據存儲的部署簡單的優點,而不必擔心給網絡用戶寫入訪問任何東西。另外,如果可能存在運行的應用程序的多個副本(例如主動 - 主動負載平衡),那麼您需要同步存儲,這對於數據庫而言比使用文件系統更容易。

如果您確實使用文件系統而不是blob,那麼問題是,您是否通過將Alias指向文件夾來讓Web服務器通過它提供服務?

  • +超快
  • +緩存以及
  • - 額外的服務器配置:虛擬目錄;需要適當的文件擴展名來返回所需Content-Type
  • - 額外的服務器配置:需要添加Content-Disposition: attachment/X-Content-Type-Options頭阻止IE瀏覽器嗅探HTML作爲防XSS的一部分措施

還是你手動提供服務的文件有一個服務器端腳本吐出來,因爲你將不得不從一個MySQL blob服務?

  • - 是潛在的慢
  • - 需要的If-Modified-由於人工的公平位和ETag處理緩存正常
  • +可以使用應用程序本身的訪問控制方法
  • +容易添加正確內容類型和內容處理標題從服務腳本

這是一個權衡沒有一個全球接受的答案。

2

許多人建議不要在數據庫中的blob中存儲文件附件(通常這適用於圖像)。相反,他們更喜歡將路徑名作爲字符串存儲在數據庫中,並將文件存儲在文件系統的某個安全位置。這有一些優點:

  • 數據庫和數據庫備份較小。
  • 如果您需要特別處理文件系統上的文件,可以更輕鬆地編輯這些文件。
  • 文件系統擅長存儲文件。數據庫擅長存儲元組。讓每個人都做它擅長的事情。

有反駁也支持將附件中的blob:

  • 刪除一行在數據庫中自動刪除相關附件。
  • 當數據連續時,回滾和事務隔離按預期工作,但當數據的某些部分位於文件系統中時不會如此。
  • 如果所有數據都在數據庫中,則備份更簡單。無需擔心在備份過程中同時更改一致的數據備份。

所以最好的解決方案取決於你將如何在你的應用程序中使用數據。沒有一個通用的答案。我知道你用MySQL標記了你的問題,但是如果讀過這個問題的人使用其他品牌的RDBMS,他們可能想要在使用Oracle時查看BFILE,或者在使用Microsoft SQL Server 2008時查看FILESTREAM。這些給你的能力將文件存儲在數據庫外部,但像訪問它們是數據庫表中某一行的一部分一樣訪問它們(或多或少)。

2

數據應該存儲在一個一致的地方:數據庫。 這個性能和內容類型的東西根本就不是問題,因爲沒有什麼能夠阻止你將這些BLOB字段緩存到本地Web服務器並在第一次請求時從那裏提供服務。您無需在每個頁面視圖中訪問該表格。

該文件系統緩存可隨時清空,這隻會在自動補充時暫時影響性能。它還將使您能夠隨着應用程序的增長使用一個數據庫和多個Web服務器,它們將簡單地在文件系統上都具有本地緩存​​。

5

根據我的經驗,在MySQL中存儲BLOB是可以的,只要您將blob存儲在一個表中,而其他字段存儲在另一個(聯接)表中。相反,在具有幾個標準字段和一個具有100 MB數據的blob字段的表的字段中搜索會顯着減慢查詢速度。

我不得不更改郵件應用程序的數據層,以解決電子郵件存儲在與發送日期,電子郵件地址等相同的表中的內容。搜索10000封電子郵件需要9秒。現在需要它應該採取什麼;-)