2012-08-31 63 views
2

我有一個數據庫設置爲在varbinary(max)字段上爲音頻文件使用blob FileStream。它的規模已經擴大到80GB以上,我面臨着性能問題。如何將文件流中的varbinary(max)轉換爲T-SQL中的實際varbinary(max)

經過一番四處張望,我發現我的平均BLOB大小約爲180K。由於根據MSDN文件流應該用於超過1MB的對象,我正在重新評估我如何存儲這些blob。 MSDN還指出:「對於較小的對象,在數據庫中存儲varbinary(max)BLOB通常會提供更好的流式處理性能。」所以我正在考慮從varbinary(max)和filestream移動到只使用varbinary(max)字段。

所以我的問題是,是否有一個很好的方式使用sql腳本將文件流中的每個文件流blob移動到實際的varbinary字段本身?我之前一直在研究的另一種方法是讓c#應用程序在數據庫中查詢blob並將每個blob寫入文件系統。然後手動從數據庫中刪除文件流的東西。然後讓c#應用程序從文件系統中讀取blob並將其寫回數據庫。我覺得必須有一個更簡單的方法。

回答

5

假設你的源表看起來像這樣:

CREATE TABLE audioFiles 
(
    AudioID INT IDENTITY NOT NULL PRIMARY KEY, 
    [Name] VARCHAR(50) NOT NULL, 
    [AudioData] VARBINARY(MAX) FILESTREAM NULL, 
    RowGuid UNIQUEIDENTIFIER NOT NULL ROWGUIDCOL UNIQUE DEFAULT(NEWID()) 
) 

然後,你可以創建一個第二表:

CREATE TABLE audioBlobs 
(
    AudioID INT IDENTITY NOT NULL PRIMARY KEY, 
    [Name] VARCHAR(50) NOT NULL, 
    [AudioData] VARBINARY(MAX) NULL, 
    RowGuid UNIQUEIDENTIFIER NOT NULL ROWGUIDCOL UNIQUE DEFAULT(NEWID()) 
) 
GO 

(請注意,FILESTREAM是從第二個表中的列AudioData失蹤.. 。導致二進制數據與頁面的其餘部分存儲在一起,而不是單獨的FILESTREAM文件組中。)

然後你可以直接插入ERT從一個表到另一個數據:

SET IDENTITY_INSERT audioBlobs ON 

INSERT INTO audioBlobs (AudioID, Name, AudioData, RowGuid) 
    SELECT AudioID, Name, AudioData, RowGuid FROM audioFiles 

SET IDENTITY_INSERT audioBlobs OFF 

一旦你完成,你可以放下你的原始表,和你的新表重命名爲原始表的名稱:

DROP TABLE audioFiles 
GO 

EXECUTE sp_rename N'dbo.audioBlobs', N'audioFiles', 'OBJECT' 
GO 

或者,您可以在原始表格中創建第VARBINARY(MAX)列,並在您的原始表格的FILESTREAM列的旁邊創建一列,然後使用舊列的數據更新新列的值。請注意,無論使用哪種方式,您的總磁盤空間使用量都會增加一倍以上 - 將實際音頻數據的空間加倍,將其從FILESTREAM文件組遷移到PRIMARY文件組(或主要數據文件所在的位置),再加上您的事務日誌中有很多空間。

+0

NEWID()不適合索引。更好地使用NEWSEQUENTIALID()來代替。 –

相關問題