【问题标题】:SQL: Sequentially doing UPDATE .WRITE on VarBinary columnSQL:按顺序对 VarBinary 列执行 UPDATE .WRITE
【发布时间】:2009-12-21 21:01:24
【问题描述】:

我正在尝试创建一个小测试应用程序,它读取 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/内存...

【问题讨论】:

    标签: c# sql sql-update varbinary


    【解决方案1】:

    FileStream 类缓冲输入和输出。您可以在每次更新后调用 Flush() 方法来清除内部缓冲区。

    明确地说,它只会缓冲到缓冲区大小 (4 KB)。

    在这种情况下,我认为你的罪魁祸首是 SqlExpress。当我执行您的代码并写入我的本地 SqlExpress 副本时,sqlsrvr 进程的内存使用量增加了大约 1 GB。当我写入非本地数据库时,我的内存使用量保持不变。

    【讨论】:

    • 这似乎有点帮助。然而,它看起来仍然增加了 50% 到 80% 的文件大小到内存中...... :(
    • 使用非本地 SQL 服务器时,此处相同。谢谢。
    • 试试 GC.Collect() 它们可能是等待收集的依赖项。
    【解决方案2】:

    它会缓冲它,因为当您将它保存到 varbinary 列时,它会成为 sql server 中 LOB 数据缓存的一部分。这就是它的工作原理。

    或者你的意思是它在其他地方缓冲?

    【讨论】:

    • 嗯,我的意思是它把它缓冲到我的机器内存中。如果我尝试将 1GB 的文件保存到列中,最终将使用 1GB 的物理内存。由于 SQL 服务器不会将所有内容保存在 RAM 中,我猜我的代码一定有问题......
    • sql server 在 RAM 中保留尽可能多的数据。所以如果可以的话,它将把 1Gb Lob 保留在内存中。要对此进行测试,只需重新启动 sql server 服务,检查 mem,重新读取 varbinary 列并再次检查 mem。
    • 我刚刚用非本地 SQL 服务器进行了测试,你是对的。我这边没有缓冲,但有时在服务器上有点缓冲。感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-29
    • 1970-01-01
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多