SQL:在 VarBinary 列上顺序执行 UPDATE .WRITE
我正在尝试创建一个小测试应用程序,它读取 FileStream 块并将其附加到 SQL Server 2005 Express 上的 VarBinary(max) 列。
一切正常 - 该列按预期填充,但我的机器似乎仍然将所有内容缓冲到内存中,我只是不明白为什么。
我正在使用以下代码 (C#):
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;
}
}
}
}
}
谁能告诉我为什么它将文件缓冲到内存中?我使用的 byte[]
缓冲区大小只有近 2 MB。
我可以为每个块创建一个新的缓冲区,但这似乎也浪费了 CPU/内存......
I'm trying to create a little test application which reads chunks of a FileStream and appends it to a VarBinary(max) column on an SQL Server 2005 Express.
Everything works - the column gets filled as it's supposed to, but my machine still seems to buffer everything into memory and I just can't see why.
I'm using the following code (C#):
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;
}
}
}
}
}
Can anybody tell me why it buffers the file into memory? The byte[]
buffer I'm using is only almost 2 MB in size.
I could create a new buffer for each chunk, but that seems like a waste of CPU/memory also...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
FileStream 类缓冲输入和输出。您可以在每次更新后调用 Flush() 方法来清除内部缓冲区。
需要明确的是,它只会缓冲最大缓冲区大小 (4 KB)。
在这种情况下,我认为你的罪魁祸首是SqlExpress。当我执行您的代码并写入 SqlExpress 的本地副本时,sqlsrvr 进程的内存使用量跃升了约 1 GB。当我写入非本地数据库时,我的内存使用量保持不变。
The FileStream class buffers input and output. You can call the Flush() method after each update to clear the internal buffers.
To be clear, it will only buffer up to the buffer size (4 KB).
In this case, I think your culprit is SqlExpress. When I executed your code and wrote to my local copy of SqlExpress, the memory usage by the sqlsrvr process jumped by around 1 GB. When I wrote to a non-local database, my memory usage remained flat.
它会缓冲它,因为当您将其保存到 varbinary 列中时,它会成为 sql server 中 LOB 数据缓存的一部分。这就是它的工作原理。
或者你的意思是它在其他地方缓冲?
it buffers it because when you save it into the varbinary column it becomes part of the LOB data cache in sql server. that's how it works.
or do you mean it gets buffered somewhere else?