SQL: последовательно выполняем UPDATE .WRITE для столбца VarBinary.
Я пытаюсь создать небольшое тестовое приложение, которое читает фрагменты FileStream и добавляет его в столбец VarBinary(max) в SQL Server 2005 Express.
Все работает - столбец заполняется, как и должно быть, но моя машина все еще, похоже, все в буфер, и я просто не понимаю, почему.
Я использую следующий код (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 МБ.
Я мог бы создать новый буфер для каждого куска, но это также похоже на трату процессорного времени / памяти...
2 ответа
Он буферизует его, потому что когда вы сохраняете его в столбце varbinary, он становится частью кэша больших объектов на сервере sql. Вот как это работает.
или ты имеешь в виду, что это буферизовано где-то еще?
Класс FileStream буферизует ввод и вывод. Вы можете вызывать метод Flush() после каждого обновления, чтобы очистить внутренние буферы.
Чтобы быть понятным, он будет только буферизировать до размера буфера (4 КБ).
В этом случае, я думаю, ваш виновник SqlExpress. Когда я выполнил ваш код и записал в свою локальную копию SqlExpress, использование памяти процессом sqlsrvr возросло примерно на 1 ГБ. Когда я писал в нелокальную базу данных, мое использование памяти оставалось неизменным.