我有一个数据库设置为在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并写回数据库。我认为必须有一个更简单的方法。
答案 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文件组(或主数据文件所在的位置),另外还有事务日志中有很多空间。