我们需要每秒存储500个测量数据,这些数据来自多个设备。每个度量由时间戳、数量类型和几个向量值组成。现在,每个测量有8个向量值,我们可以认为这个数字是不变的,以满足我们的原型项目的需要。我们正在使用HNibernate。测试是在SQLite中完成的(磁盘文件db,而不是内存中的),但是生产可能是MsSQL。
我们的测量实体类是一个包含单个度量的类,如下所示:
public class Measurement
{
public virtual Guid Id { get; private set; }
public virtual Device Device { get; private set; }
public virtual Timestamp Timestamp { get; private set; }
public virtual IList<VectorValue> Vectors { get; private set; }
}向量值存储在单独的表中,因此每个表都通过外键引用其父度量。
我们已经做了几件事情来确保生成的SQL是(合理的)有效的:我们使用Guid.Comb生成is,我们在一个事务中刷新大约500个条目,ADO.Net批处理大小被设置为100 (我认为SQLIte不支持批处理更新?但以后可能会有用)。
问题
现在,我们可以插入每秒150-200个测量数据(这还不够快,尽管这是我们正在讨论的SQLite )。查看生成的SQL,我们可以看到在单个事务中插入(如预期的):
这意味着我们实际上做了10倍多的单表插入:每秒1500到2000次。
如果我们将所有内容(所有8个向量值和时间戳)放入度量表(添加9个专用列),似乎可以将插入速度提高10倍。
切换到SQL server将提高性能,但我们想知道是否有一种方法可以避免与数据库组织方式有关的不必要的性能成本。
编辑
使用内存中的SQLite,我可以获得大约350个条目/秒(3500个单表插入),我认为这与使用NHibernate (本文参考:http://ayende.com/Blog/archive/2009/08/22/nhibernate-perf-tricks.aspx)一样好。
但我最好还是改用SQL server,停止假设,对吧?我一测试就会更新我的帖子。
更新
我已经迁移到了SQL server,并将我的层次结构夷为平地,我对它进行了测试,每秒钟存储3000条测量数据,时间长达几个小时,而且它似乎运转良好。
发布于 2010-05-03 11:16:41
就我个人而言,我会说“去做”:去normalized,然后创建一个ETL过程,将这些数据转换成一种更规范化的格式,以便进行分析/定期使用。
基本上,理想的情况可能是拥有一个单独的数据库(如果需要的话,甚至在同一个数据库中只有单独的表),它将数据的获取与需要处理数据的格式完全不同。
这并不意味着您需要丢弃围绕当前数据库结构创建的实体:只是您还应该创建那些非规范化表并创建一个ETL来引入它们。您可以使用SSIS (尽管它仍然非常错误和易怒)定期将数据带到规范化的表集中,甚至可以使用C#应用程序或其他批量加载过程。
编辑:当然,这是假设您的分析不需要实时完成:只是收集数据。很多时候,人们不需要(有时,实际上也不希望)实时更新分析数据。这是纸面上听起来不错的事情之一,但在实践中却是不必要的。
如果一些分析这些数据的人需要实时访问,那么如果需要的话,可以针对“裸金属”非规范化的事务性数据构建工具集:但是当您真正深入分析需求时,执行分析的人员通常不需要真正的实时(在某些情况下,他们更喜欢使用更静态的数据集!):在这种情况下,周期性的ETL会运行得很好。你只需要和你的目标用户聚在一起,找出他们真正需要的东西。
发布于 2010-05-03 17:55:37
那得看情况了。8向量值是一个永不改变的硬和快速的数字吗?然后,在您的情况下反错可能是有意义的(但只有在您使用的真正硬件和数据库上的测试才能说明问题)。如果下周可能有9次测量,那就不要这么做。
我想说的是,您需要先切换到SQL server和将要运行的设备,然后才能决定要做什么。
一旦你切换了运行分析器。nHibernate完全可能没有为您的插入创建性能最好的SQl。
事实上,您有一组向量,这些向量可能在插入时被拆分,这可能是性能问题的一部分。最好有8个独立的变量,而不是一个必须拆分的集合。
你说的是每天超过4000万个记录,这将需要一些主要的硬件和一个设计良好的数据库。也有可能是关系数据库不是最好的选择(我不知道您想如何使用这么多数据)。你把这些数据保存多久,这里的大小很快就会失控。
是否有可能在一组中每分钟插入一次记录?大容量插入比逐行插入要快得多。
您的设计必须考虑如何使用数据以及如何插入数据。通常情况下,为了加速插入所做的事情会减慢选择速度,反之亦然。您可能需要一个每天加载一次以进行分析的数据仓库(以及一个快速查询,以便能够显示原始数据直到第二个数据)。
发布于 2010-05-03 11:38:32
首先,移到目标数据库;基于SqlLite的性能可能不是基于MsSql的性能指示
其次,度量性能瓶颈所在;我冒昧地冒险说,这是磁盘,内存中的数据库执行起来要好得多。
然后,如果必要的话,按照上面的建议,使用ETL过程进行去甲基化。
事件流处理有句谚语:“如果你点击磁盘,你就死定了。”
https://stackoverflow.com/questions/2757590
复制相似问题