- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我们有这样的代码:
ms = New IO.MemoryStream
bin = New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
bin.Serialize(ms, largeGraphOfObjects)
dataToSaveToDatabase = ms.ToArray()
// put dataToSaveToDatabase in a Sql server BLOB
但是内存流从大内存堆中分配了一个大缓冲区,这给我们带来了问题。那么我们如何在不需要足够的可用内存来保存序列化对象的情况下传输数据呢?
我正在寻找一种从 SQL Server 获取 Stream 的方法,然后将其传递给 bin.Serialize() ,从而避免将所有数据保留在我的进程内存中。
读回数据也是如此...
<小时/>更多背景信息。
这是复杂的数字处理系统的一部分,该系统近乎实时地处理数据以查找设备问题等,完成序列化是为了在数据源等的数据质量出现问题时允许重新启动。(我们存储数据馈送,并可以在运算符(operator)编辑掉错误值后重新运行它们。)
因此,我们序列化对象的频率比反序列化它们的频率要高得多。
我们正在序列化的对象包括非常大的数组(大部分为 double )以及许多小的“更正常”对象。我们正在插入 32 位系统的内存限制,并使垃圾收集器非常努力地工作。 (系统中的其他地方正在采取措施来改善这一点,例如重用大型数组而不是创建新数组。)
状态的序列化通常是 last straw导致内存不足异常;我们的内存使用高峰总是在此序列化步骤。
我认为当我们反序列化对象时,我们会得到大的内存池碎片,考虑到数组的大小,我预计大内存池碎片还会存在其他问题。 (这还没有被调查,因为首先看到这个的人是数值处理专家,而不是内存管理专家。)
我们的客户混合使用 SQL Server 2000、2005 和 2008,如果可能的话,我们不希望每个版本的 SQL Server 使用不同的代码路径。
我们一次可以有许多事件模型(在不同的进程中,跨多台机器),每个模型可以有许多保存的状态。因此,保存的状态存储在数据库 blob 中,而不是文件中。
由于保存状态的传播很重要,我宁愿不将对象序列化到文件,然后将文件一次一个 block 地放入 BLOB 中。
我问过的其他相关问题
最佳答案
没有内置的 ADO.Net 功能可以真正优雅地处理大数据。问题有两个:
FileStream
)接受流以从中READ,这与write的序列化语义不一致成一条流。无论你以哪种方式改变它,你最终都会得到整个序列化对象的内存副本,这很糟糕。所以你真的必须从不同的角度来处理这个问题。幸运的是,有一个相当简单的解决方案。诀窍是使用高效的 UPDATE .WRITE
语法,并在一系列 T-SQL 语句中逐个传入数据 block 。这是MSDN推荐的方式,参见Modifying Large-Value (max) Data in ADO.NET 。这看起来很复杂,但实际上做起来很简单,并将其插入 Stream 类中。
BlobStream 类
这是解决方案的基础。 Stream 派生类,将 Write 方法实现为对 T-SQL BLOB WRITE 语法的调用。直接来说,唯一有趣的是它必须跟踪第一次更新,因为 UPDATE ... SET blob.WRITE(...) 语法在 NULL 字段上会失败:
class BlobStream: Stream
{
private SqlCommand cmdAppendChunk;
private SqlCommand cmdFirstChunk;
private SqlConnection connection;
private SqlTransaction transaction;
private SqlParameter paramChunk;
private SqlParameter paramLength;
private long offset;
public BlobStream(
SqlConnection connection,
SqlTransaction transaction,
string schemaName,
string tableName,
string blobColumn,
string keyColumn,
object keyValue)
{
this.transaction = transaction;
this.connection = connection;
cmdFirstChunk = new SqlCommand(String.Format(@"
UPDATE [{0}].[{1}]
SET [{2}] = @firstChunk
WHERE [{3}] = @key"
,schemaName, tableName, blobColumn, keyColumn)
, connection, transaction);
cmdFirstChunk.Parameters.AddWithValue("@key", keyValue);
cmdAppendChunk = new SqlCommand(String.Format(@"
UPDATE [{0}].[{1}]
SET [{2}].WRITE(@chunk, NULL, NULL)
WHERE [{3}] = @key"
, schemaName, tableName, blobColumn, keyColumn)
, connection, transaction);
cmdAppendChunk.Parameters.AddWithValue("@key", keyValue);
paramChunk = new SqlParameter("@chunk", SqlDbType.VarBinary, -1);
cmdAppendChunk.Parameters.Add(paramChunk);
}
public override void Write(byte[] buffer, int index, int count)
{
byte[] bytesToWrite = buffer;
if (index != 0 || count != buffer.Length)
{
bytesToWrite = new MemoryStream(buffer, index, count).ToArray();
}
if (offset == 0)
{
cmdFirstChunk.Parameters.AddWithValue("@firstChunk", bytesToWrite);
cmdFirstChunk.ExecuteNonQuery();
offset = count;
}
else
{
paramChunk.Value = bytesToWrite;
cmdAppendChunk.ExecuteNonQuery();
offset += count;
}
}
// Rest of the abstract Stream implementation
}
<小时/>
使用 BlobStream
要使用这个新创建的 blob 流类,您需要将其插入到 BufferedStream 中。该类的设计很简单,仅处理将流写入表的列中。我将重用另一个示例中的表格:
CREATE TABLE [dbo].[Uploads](
[Id] [int] IDENTITY(1,1) NOT NULL,
[FileName] [varchar](256) NULL,
[ContentType] [varchar](256) NULL,
[FileData] [varbinary](max) NULL)
我将添加一个要序列化的虚拟对象:
[Serializable]
class HugeSerialized
{
public byte[] theBigArray { get; set; }
}
最后,实际的序列化。我们首先将一条新记录插入 Uploads
表中,然后在新插入的 Id 上创建一个 BlobStream
并直接在此流中调用序列化:
using (SqlConnection conn = new SqlConnection(Settings.Default.connString))
{
conn.Open();
using (SqlTransaction trn = conn.BeginTransaction())
{
SqlCommand cmdInsert = new SqlCommand(
@"INSERT INTO dbo.Uploads (FileName, ContentType)
VALUES (@fileName, @contentType);
SET @id = SCOPE_IDENTITY();", conn, trn);
cmdInsert.Parameters.AddWithValue("@fileName", "Demo");
cmdInsert.Parameters.AddWithValue("@contentType", "application/octet-stream");
SqlParameter paramId = new SqlParameter("@id", SqlDbType.Int);
paramId.Direction = ParameterDirection.Output;
cmdInsert.Parameters.Add(paramId);
cmdInsert.ExecuteNonQuery();
BlobStream blob = new BlobStream(
conn, trn, "dbo", "Uploads", "FileData", "Id", paramId.Value);
BufferedStream bufferedBlob = new BufferedStream(blob, 8040);
HugeSerialized big = new HugeSerialized { theBigArray = new byte[1024 * 1024] };
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(bufferedBlob, big);
trn.Commit();
}
}
<小时/>
如果您监视这个简单示例的执行,您会发现没有任何地方创建大型序列化流。该示例将分配 [1024*1024] 的数组,但这只是出于演示目的,以便有一些内容可以序列化。此代码以缓冲方式逐 block 序列化,使用 SQL Server BLOB 建议的每次更新大小 8040 字节。
关于.net - 如何在不创建大缓冲区的情况下将大型 .NET 对象图序列化为 SQL Server BLOB?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2101149/
我正在阅读 Python 文档以真正深入了解 Python 语言,并遇到了 filter 和 map 函数。我以前使用过过滤器,但从未使用过映射,尽管我在 SO 上的各种 Python 问题中都见过这
当我尝试打印 BST 的级别顺序时,这个问题提示了我。 这是一个 Pre-Order Sequence: 4, 1, 2, 3, 5, 6, 7, 8 In_order Sequence : 1, 2
我的代码在 main(序列测试;)的第一行出现错误,指出它是对 sequence::sequence() 的 undefined reference 。我无法更改 main 中的代码。有谁知道我该如何
这可能很简单,但我在通常的 latex 指南中找不到任何相关内容。在这句话中: {\em hello\/} “\/”的目的是什么? 最佳答案 这就是所谓的斜体校正。其目的是确保斜体文本后有适当的间距。
当我从 Postgresql 表中删除所有记录,然后尝试重置序列以在插入时开始一个编号为 1 的新记录时,我得到不同的结果: SELECT setval('tblname_id_seq', (SELE
在版本10.0.3中,MariaDB引入了一种称为序列的存储引擎。 其ad hoc为操作生成整数序列,然后终止。 该序列包含正整数,以降序或升序排列,并使用起始,结束和递增值。 它不允许在多个查询中
如何在 Groovy 中获取给定数字的序列,例如: def number = 169 // need a method in groovy to find the consecutive number
基本上,如果这是 .NET,它看起来像这样: ISomething { string A { get; } int B { get; } } var somethings = new List
说以下代码部分(同一块): A <= 1 A <= 2 变量 A 总是被赋值为 2 吗?还是会出现竞争条件并分配 1 或 2? 我对非阻塞赋值的理解是,由硬件在 future 分配变量 A,因此它可能
在运行 WiX 设置时,我正在寻找操作列表及其顺序。不知何故,官方网站似乎没有提供任何信息。 基本问题是我想正确安排我的自定义操作。通常我需要使用 regsvr32.exe 注册一个 DLL,而这只能
F#初学者在这里 我想创建一个类型,它是具有至少一个元素的另一种具体类型(事件)的序列。任何其他元素都可以在以后随时添加。通常在 C# 中,我会创建一个具有私有(private) List 和公共(p
作为构建过程和不断发展的数据库的一部分,我试图创建一个脚本,该脚本将删除用户的所有表和序列。我不想重新创建用户,因为这将需要比所允许的更多的权限。 我的脚本创建了一个过程来删除表/序列,执行该过程,然
我想恢复两个向量的第一个日期和相同向量的第二个日期之间的日期序列,.... 这是一个例子: dates1 = as.Date(c('2015-10-01', '2015-03-27', '2015-0
这个问题已经有答案了: sql ORDER BY multiple values in specific order? (12 个回答) 已关闭 9 年前。 我有一个 sql 语句,我想要ORDER
我想恢复两个向量的第一个日期和相同向量的第二个日期之间的日期序列,.... 这是一个例子: dates1 = as.Date(c('2015-10-01', '2015-03-27', '2015-0
在用java编写代码时,我需要用“],[”分割字符串。下面是我的代码。 try (BufferedReader reader = new BufferedReader(new InputStreamR
这个问题已经有答案了: Project Euler Question 14 (Collatz Problem) (8 个回答) 已关闭 9 年前。 我正在尝试查找数字的 Collatz 序列。以下
我有一个例程函数process_letter_location(const char& c, string &word)。 在我的 main 中,我声明了一系列字符串变量,如下所示: string s
我需要找到最长的多米诺骨牌链,给定一组 12 个随机挑选的多米诺骨牌。我已经递归地生成了多米诺骨牌的所有可能性(使用 0 到 12 的面值有 91 种可能性)。多米诺骨牌由一 block “砖 blo
我有这个数据结构 Seq,它继承了类 vector 但有一些额外的功能。使用这个数据结构 Seq 我有这个预定义的数据结构: typedef Seq > MxInt2d; 我现在想要一个包含多个 Mx
我是一名优秀的程序员,十分优秀!