【发布时间】:2019-09-04 06:19:05
【问题描述】:
我想使用 T-SQL 将文件复制到 SQL Server 文件表。我不能使用 Win32 API(或SqlFileStream 类),因为服务器不公开 SMB。以下代码非常适用于较小的文件(最大 1GB):
using (SqlConnection conn = new SqlConnection(connStr))
using (SqlCommand cmd = conn.CreateCommand())
using (Stream file = File.OpenRead(@"c:\Path\To\Large\file.bin"))
{
conn.Open();
cmd.CommandTimeout = 3600;
cmd.CommandText = "UPDATE file_table SET file_stream = @stream WHERE path_locator = GetPathLocator(@path)";
cmd.Parameters.AddWithValue("@path", @"\\HOST\INSTANCE\DB\file_table\largetest.bin");
cmd.Parameters.Add("@stream", System.Data.SqlDbType.Binary, -1).Value = file;
cmd.ExecuteNonQuery();
}
性能不错(大约 100MB/s),并且传递流也很有效,并且很容易占用客户端的内存。但是,我看到在此查询期间服务器的内存使用量激增 - 显然,SQL Server 将整个流复制到内存中,然后再将其写入磁盘。我还看到 tempdb 的磁盘 IO。查询有时会成功,但对于同一文件,有时会失败。文件大小在 1.5GB 左右开始出现错误我从来没有成功处理过 4GB 的文件。如果查询失败,我会收到以下异常:
System.Data.SqlClient.SqlException: 'Internal error: An expression services limit has been reached. Please look for potentially complex expressions in your query, and try to simplify them.'
有没有更好的方法将大文件放入文件表中?
【问题讨论】:
-
您是否正在将 2GB 的 blob 加载到数据库中?如果是,为什么?
-
@gvee SQL Filetables 实际上是用来存储大文件的。它实际上并不将它们存储在数据库中,而是将它们存储在文件系统中并为其提供 T-SQL 接口。原因是我的应用程序需要一个位置来存储所有客户端的文件以及一个数据库,而我只想为两者公开一个服务器接口。
标签: c# sql-server filestream sqlclient filetable