.net – 我们应该对数据库进行非规范化以提高性能吗?

我们要求每秒存储500个测量值,来自多个设备.每个测量由时间戳,数量类型和几个向量值组成.现在每个测量值有8个矢量值,我们可以认为这个数字对于我们的原型项目的需求是不变的.我们正在使用HNibernate.测试在sqlite(磁盘文件db,而不是内存)中完成,但生产可能是Mssql.

我们的Measurement实体类是持有单一度量的类,如下所示:

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来生成ID,我们在单个事务中刷新大约500个项目,ADO.Net批量大小设置为100(I认为sqlIte不支持批量更新,但稍后可能会有用.

问题

现在我们可以每秒插入150-200个测量(这不够快,尽管这是我们正在讨论的sqlite).看看生成sql,我们可以看到,在单个事务中,我们插入(如预期的):

> 1个时间戳
> 1测量
> 8个矢量值

这意味着我们实际上在做多10倍的单表插入:1500-2000每秒.

如果我们将所有(所有8个向量值和时间戳)都放入测量表(添加9个专用列)中,似乎可以将插入速度提高10倍.

切换到sql服务器将提高性能,但是我们想知道是否有可能避免与数据库组织方式相关的不必要的性能成本.

[编辑]

使用内存中的sqlite我可以获得约350个项目/秒(3500个单表插入),我相信与NHibernate一样好(参考这篇文章http://ayende.com/Blog/archive/2009/08/22/nhibernate-perf-tricks.aspx).

但是我也可以切换到sql服务器并停止假设事情,对吧?一旦我测试,我会更新我的帖子.

[更新]

我已经转移到sql服务器并平整了我的层次结构,我通过存储3000个测量/秒来测试它几个小时,似乎工作正常.

解决方法

就我个人而言,我会说:反规范化,然后创建一个ETL过程,使这些数据进入更规范化的格式进行分析/定期使用.

基本上,您的理想情况可能是拥有一个单独的数据库(或者甚至只需在同一个数据库中分离表,如果需要),将数据采集作为一个完全独立的事项,将其以需要处理的格式它.

这并不意味着您需要丢弃您在当前数据库结构周围创建的实体:只要您也应该创建这些非规范化表并使其成为一个ETL.您可以使用SSIS(尽管它仍然是相当错误和易怒)将数据定期进入您的标准化表,甚至是C#应用程序或其他批量加载过程.

编辑:这是假设,当然,您的分析不需要实时完成:只是数据的收集.人们通常不需要(有时甚至不愿意)实时更新分析数据.这是在纸上听起来不错的东西之一,但实际上是没有必要的.

如果有些分析这些数据的人需要实时访问,那么您可以根据需要构建一个针对“裸机”非规范化事务数据的工具集,但是当您真正了解需求时,您可以非常频繁地执行分析,不需要真正的实时(在某些情况下,他们更喜欢使用更静态的数据集!):在这种情况下,定期的ETL可以运行得很好.你只需要与目标用户聚在一起,找出真正需要的内容.

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 &#39;EastRiver&#39; 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...