SQL Server FILESTREAM 限制

13

我正在研究 SQL Server 中的 FILESTREAM 属性以将文件存储在其中。我了解它将文件存储在硬盘上,并将文件指针/路径信息存储在数据库中,同时在处理过程中保持事务一致性。

FILESTREAM 属性还有一个限制:“只能将 FILESTREAM 数据存储在本地磁盘卷上”。

如果我预计我的 web 应用程序需要存储 200,000 张每张 1-2MB 的图片,那么我需要大约 200GB 的硬盘空间来存储这些图像。由于 FILESTREAM 要求所有数据仅存储在本地磁盘上,因此要在单个硬盘上存储数百万个文件是不可能的,因为存储要求会非常大。

我的理解是否正确,或者我漏掉了什么?

如果这个限制是正确的,那么我会将其存储为纯粹的 blob,并将我的 DB 集群化以增加存储需求,这似乎无法使用 FILESTREAM 实现。

请分享您的想法!

更新:
关于 FILESTREAM 还有一些问题:-

  1. 如何处理数据容器损坏的情况下的数据恢复?
  2. 我们可以仅备份数据库而不备份文件系统数据吗?[假设数据在 SAN 中,无需移动]
  3. 我想备份或还原数据库并重新映射文件组路径信息[映射到 SAN]。这可行吗?
4个回答

19

FILESTREAM并不实际要求使用本地存储,只是不允许使用SMB网络存储。iSCSI或Fiber Channel SAN可用于存储FILESTREAM数据。您还可以在每个表中拥有多个filestream文件组,从而分区您的数据。如果严格针对SQL Server 2008,使用FILESTREAM来处理大型二进制数据几乎没有任何理由不这样做。这里有一篇微软白皮书描述了FILESTREAM分区(链接)


@Jeff:很棒的帖子!它提供了很多清晰度和一些我更新的问题。 - pencilslate

4

关于本地磁盘卷需求

不要过于字面理解“本地”。虽然MSSQL确实需要“看到”与FILESTREAM数据相关的文件组作为本地驱动器,但这种存储通常通过NAS或其他存储技术提供,这些技术通过iSCSI等方式欺骗Windows认为这些是本地NTFS磁盘。特别是对于企业应用程序,您提到的空间需求级别更高。

是否使用FILESTREAM...

请仔细权衡利弊。您的问题提到了相当大的(MB级别)图像(我假设是图形图像,而不是逻辑图像),这意味着它们的使用相当原子化。文件服务器设置需要外部(SQL服务器之外的)管理和同步,但这似乎是一个相对较小的代价,以保持您的自由,不仅是与SQL Server / Microsoft相关,而且还有您轻松移动事物以进行扩展/带宽目的的能力。


1
@mjv:移动事物的自由是最主要的关注点。在数据容器损坏期间会发生什么?仅备份数据库并稍后重新映射文件组路径的能力?这些都是根据您的解释出现的一些问题。 - pencilslate
1
@pencilslate:SQL Server 能够有效地管理 FILESTREAM(FS)数据存储,因此 FS 存储的备份是 SQL 备份/恢复模型的一部分。可以明确地从常规 SQL 备份中排除与 FS 相关的存储位置,并在外部管理此备份;这样做往往会破坏其目的,因此必须在极大的备份/恢复或手动管理单独恢复计划之间进行选择... 因此,除非将两种数据类型集成到一起具有强大的优势,否则完全外部的存储库系统可能更可取。 - mjv
1
非文件系统解决方案的一个可能的FS类型数据恢复策略是在不同物理位置有两个在线存储库。这些存储库并行更新,最小化了频繁进行“磁带”备份的需求。次要存储库不仅作为备份,而且作为待机服务器。当存储的数据是图像、PDF和其他压缩效果不佳的内容时,这尤其有趣,因此正式备份或镜像设置需要相似的存储量。 - mjv
1
自由被高估了。如果微软能继续提供我优质的产品,我很乐意为他们效劳。相比于任何混合使用php、mysql、java等技术的环境,我更喜欢完全基于微软的环境。如果你在商业环境中使用SQL Server,那么除了Oracle,没有其他数据库管理系统可以替代它。试图避免不可避免的事情是没有意义的。 - Drunken Code Monkey
请记住,您还可以通过实例中的选项将文件共享。您并不真正被锁定,可以像任何其他文件系统一样复制文件,或将其重新索引到另一个数据库中。 - Drunken Code Monkey

2

使用SQL集群并不能提供额外的存储可用性,因为群集需要SAN存储。您可以在非群集实例上简单地创建LUN或多个LUN以用作FILESTREAM存储。


@mrdenny:我能否只备份数据库并在恢复后重新映射LUN,从而避免备份文件系统数据的需要? - pencilslate
如果您正在使用FILESTREAM,那么当您备份数据库时,文件也会被一并备份。 - mrdenny

1

逐步实现SQL Server 2008中的本地文件流

配置SQL Server中的文件流:

  1. 首先进入SQL Server配置管理器。
  2. 右键单击QL服务器(SQLEXPRESS)并选择属性。
  3. 选择文件流选项卡并启用文件流。

在SQL Server 2008中执行以下脚本:

EXEC sp_configure filestream_access_level, 2 RECONFIGURE

创建文件流数据库:
CREATE DATABASE MyFsDb 
ON
PRIMARY ( NAME = MyFsDat,
    FILENAME = 'c:\data\myfsdat.mdf'),
FILEGROUP MyFsGroup CONTAINS FILESTREAM( NAME = MyFs,
    FILENAME = 'c:\data\myfs1')
LOG ON  ( NAME = MyFsLog,
    FILENAME = 'c:\data\myfslog.ldf')
GO

创建表格:
CREATE TABLE MyFsTable
(
  fId INT IDENTITY PRIMARY KEY,
  fData VARBINARY(MAX) FILESTREAM  NULL,
  fName NVARCHAR(300),
  RowGuid UNIQUEIDENTIFIER  NOT NULL  ROWGUIDCOL UNIQUE DEFAULT NEWID()
)

在表中添加数据的步骤如下:

ALTER PROCEDURE [dbo].[uspAddFile]

@fData VARBINARY(Max),
@ fName varchar(50),

AS
BEGIN
INSERT INTO MyFsTable (fData, fName, RowGuid) VALUES (@Item, @ItemName, DEFAULT)
END

让我们使用C#在前端向表中添加一些数据:

Public void AddFile()
{
string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["connectionstring"].ToString();
                con = new System.Data.SqlClient.SqlConnection(connectionString);
                cmd = new System.Data.SqlClient.SqlCommand("uspAddFile", con);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Add("@fData", SqlDbType.Binary).Value = GetByte(TempPath);
                cmd.Parameters.Add("@fName", SqlDbType.VarChar).Value = tempFile;
                con.Open();
                result = cmd.ExecuteNonQuery();
                con.Close();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接