如何在文件流中将varbinary(max)转换为T-SQL中的实际varbinary(max)

时间:2012-08-31 15:08:04

标签: tsql blob filestream

我有一个数据库设置为在varbinary(max)字段上使用blob FileStream来处理音频文件。它的尺寸增加了80GB以上,我面临性能问题。

在做了一些环顾之后,我发现我的平均斑点大小约为180k。因为根据MSDN文件流应该用于超过1MB的对象,我正在重新评估我如何存储这些blob。 MSDN还指出,“对于较小的对象,在数据库中存储varbinary(max)BLOB通常可以提供更好的流式传输性能。”所以我正在考虑从文件流的varbinary(max)转到使用varbinary(max)字段。

所以我的问题是,有没有一种很好的方法使用sql脚本将每个文件流blob从文件流移动到实际的varbinary字段本身?在我决定要求之前,我一直在研究的另一种方法是让c#app查询数据库中的blob并将每个blob写入文件系统。然后从数据库中手动删除文件流内容。然后让c#app从文件系统中读取blob并写回数据库。我认为必须有一个更简单的方法。

1 个答案:

答案 0 :(得分:6)

假设您的源表如下所示:

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

(请注意,第二个表中的AudioData列中缺少FILESTREAM ...导致二进制数据与页面的其余部分一起存储在页面上,而不是存储在单独的FILESTREAM文件组中。)

然后您可以将数据从一个表插入到另一个表中:

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文件组(或主数据文件所在的位置),另外还有事务日志中有很多空间。