C# SQL:按顺序执行更新。在VarBinary列上写入
我正在尝试创建一个小测试应用程序,它读取文件流的块并将其附加到SQLServer2005Express上的VarBinary(max)列 每件事都能正常工作——专栏按预期的方式被填满,但我的机器似乎仍能将所有内容缓冲到内存中,我就是不明白为什么 我正在使用以下代码(C#): 有人能告诉我为什么它会将文件缓冲到内存中吗?我使用的C# SQL:按顺序执行更新。在VarBinary列上写入,c#,sql,sql-update,varbinary,C#,Sql,Sql Update,Varbinary,我正在尝试创建一个小测试应用程序,它读取文件流的块并将其附加到SQLServer2005Express上的VarBinary(max)列 每件事都能正常工作——专栏按预期的方式被填满,但我的机器似乎仍能将所有内容缓冲到内存中,我就是不明白为什么 我正在使用以下代码(C#): 有人能告诉我为什么它会将文件缓冲到内存中吗?我使用的byte[]缓冲区的大小几乎只有2MB 我可以为每个块创建一个新的缓冲区,但这似乎也是对CPU/内存的浪费…它会对其进行缓冲,因为当您将其保存到varbinary列时,它会
byte[]
缓冲区的大小几乎只有2MB
我可以为每个块创建一个新的缓冲区,但这似乎也是对CPU/内存的浪费…它会对其进行缓冲,因为当您将其保存到varbinary列时,它会成为sql server中LOB数据缓存的一部分。这就是它的工作原理
还是说它在其他地方被缓冲?FileStream类缓冲输入和输出。您可以在每次更新后调用Flush()方法来清除内部缓冲区 要明确的是,它将只缓冲到缓冲区大小(4KB)
在这种情况下,我认为你的罪魁祸首是SqlExpress。当我执行您的代码并写入SqlExpress的本地副本时,sqlsrvr进程的内存使用量增加了大约1GB。当我写入非本地数据库时,我的内存使用率保持不变。我的意思是,它会将其缓冲到我的机器内存中。如果我试图将一个1GB的文件保存到列中,它最终将使用1GB的物理内存。由于SQL server并没有将其所有内容保存在RAM中,我猜我的代码一定出了问题……SQL server在RAM中保存了尽可能多的数据。因此,如果可以,它将在内存中保留1Gb Lob。要测试这一点,只需重新启动sql server服务,检查mem,重新读取varbinary列,然后再次检查mem。在我的端没有缓冲,但有时在服务器上有一点缓冲。谢谢你的帮助!这似乎有点帮助。然而,看起来它仍然将50%到80%的文件大小添加到内存中…:(此处相同,当使用非本地SQL server时。谢谢。请尝试GC.Collect(),它们可能是等待收集的依赖项。
using (IDbConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings[1].ConnectionString))
{
connection.Open();
string id = Guid.NewGuid().ToString();
using (IDbCommand command = connection.CreateCommand())
{
command.CommandText = "INSERT INTO [BLOB] ([Id],[Data]) VALUES (@p1,0x0)";
SqlParameter param = new SqlParameter("@p1", SqlDbType.VarChar);
param.Value = id;
command.Parameters.Add(param);
command.ExecuteNonQuery();
}
if (File.Exists(textBox1.Text))
{
using (IDbCommand command = connection.CreateCommand())
{
command.CommandText = "UPDATE [BLOB] SET [Data].WRITE(@data, @offset, @len) WHERE [Id]=@id";
SqlParameter dataParam = new SqlParameter("@data", SqlDbType.VarBinary);
command.Parameters.Add(dataParam);
SqlParameter offsetParam = new SqlParameter("@offset", SqlDbType.BigInt);
command.Parameters.Add(offsetParam);
SqlParameter lengthParam = new SqlParameter("@len", SqlDbType.BigInt);
command.Parameters.Add(lengthParam);
SqlParameter idParam = new SqlParameter("@id", SqlDbType.VarChar);
command.Parameters.Add(idParam);
idParam.Value = id;
using (FileStream fs = new FileStream(textBox1.Text, FileMode.Open, FileAccess.Read, FileShare.Read))
{
byte[] buffer = new byte[2090400]; //chunk sizes that are multiples of 8040 bytes.
int read = 0;
int offset = 0;
while ((read = fs.Read(buffer, 0, buffer.Length)) > 0)
{
dataParam.Value = buffer;
offsetParam.Value = offset;
lengthParam.Value = read;
command.ExecuteNonQuery();
offset += read;
}
}
}
}
}