NHibernate插入/查找性能

NHibernate插入/查找性能,nhibernate,s#arp-architecture,Nhibernate,S#arp Architecture,我有几个XML文件,每个文件都包含“根对象”的数据,我使用Linq to XML解析这些数据,然后使用NHibernate和sharp architecture存储库创建实际的根对象。我已经开始优化数据插入,并在大约1小时40分钟内将30000个对象添加到数据库中。然而,这仍然太慢 我认为一个瓶颈是在数据库中查找需要IO的对象。必须查找对象以进行重用 根对象有几个作者: public virtual IList<Author> Authors { get; set; } 通过使用键

我有几个XML文件,每个文件都包含“根对象”的数据,我使用Linq to XML解析这些数据,然后使用NHibernate和sharp architecture存储库创建实际的根对象。我已经开始优化数据插入,并在大约1小时40分钟内将30000个对象添加到数据库中。然而,这仍然太慢

我认为一个瓶颈是在数据库中查找需要IO的对象。必须查找对象以进行重用

根对象有几个作者:

public virtual IList<Author> Authors { get; set; }
通过使用键入的Id(我通常不会这么做),我实现了极大的速度:

我是这样查找作者的:

LastName LastName = LastNameRepository.Get(TLastName);

                        if (LastName == null)
                        {
                            LastName = LastNameRepository.Save(new LastName(TLastName));
                            LastNameRepository.DbContext.CommitChanges();
                        }
                        Author.LastName = LastName;
propertyValues = new Dictionary<string, object>();               
propertyValues.Add("Initials", Author.Initials);
                    propertyValues.Add("ForeName", Author.ForeName);
                    propertyValues.Add("LastName", Author.LastName);
                    Author TAuthor = AuthorRepository.FindOne(propertyValues);

                    if (TAuthor == null)
                    {
                        AuthorRepository.SaveOrUpdate(Author);
                        AuthorRepository.DbContext.CommitChanges();
                        Root.Authors.Add(Author);
                    }
                    else
                    {
                        Root.Authors.Add(TAuthor);
                    }
propertyValues=newdictionary();
propertyValues.Add(“缩写”,Author.Initials);
propertyValues.Add(“ForeName”,Author.ForeName);
propertyValues.Add(“LastName”,Author.LastName);
Author tautor=AuthorRepository.FindOne(propertyValues);
if(tautor==null)
{
AuthorRepository.SaveOrUpdate(作者);
AuthorRepository.DbContext.CommitChanges();
Root.Authors.Add(Author);
}
其他的
{
Root.Authors.Add(tautor);
}
我能改进一下吗?我应该使用存储过程/HQL/pure-SQL/ICriteria来执行查找吗?我可以使用某种形式的缓存来加速查找并减少IO吗?佣金似乎是必要的,还是我应该把所有的东西都打包成一个事务

我已经每10个根对象刷新会话等

任何反馈都是非常欢迎的。非常感谢

致以最良好的祝愿


Christian

我要做的第一件事是简化Authors实体,因为我认为您不需要将缩写、ForeName和LastName对象作为单独的实体。我认为使用普通字符串会更有效:

public class Author : Entity
{   
    public virtual string Initials { get; set; }
    public virtual string ForeName { get; set; }
    public virtual string LastName { get; set; }
}

我要做的第一件事是简化Authors实体,因为我认为您不需要将Initials、ForeName和LastName对象作为单独的实体。我认为使用普通字符串会更有效:

public class Author : Entity
{   
    public virtual string Initials { get; set; }
    public virtual string ForeName { get; set; }
    public virtual string LastName { get; set; }
}

老实说,我想说你甚至不应该用SA/NHibernate来做这样的事情。这是一个从XML批量导入数据的过程——像SSIS这样的ETL工具将是一个更好的选择。即使是在DB服务器上手动启动的进程也会工作得更好——步骤1,将XML加载到表中,步骤2,执行UPSERT。顺便提一下,SQL 2008为UPSERT操作引入了MERGE命令,这可能很有用

我也同意Dan的评论——是否真的有必要将姓名首字母、名字和姓氏视为单独的实体?将它们视为简单字符串可以提高性能。在您的域模型中,什么指定了它们本身就是实体

如果您确实必须继续使用SA/NHibernate,请阅读以下内容:

Jimmy博客中关于批处理选择的建议应该会有很大帮助。如果您计划一次处理一批250条记录,请将所有选择作为单个NH命令执行,处理所有数据,然后将所有更新作为另一个单独的批执行(我相信您使用EntityWithTypedId和adonet.batch\u size config设置将有助于实现这一点)

最后,关于“我使用Linq解析为XML”的语句,这真的是最好的方法吗?考虑到输入文件的大小,我猜可能是这样的,但是您知道将XML文件反序列化为对象图的方法吗?因此,我不想在描述这一点的页面上发布链接,因为我还没有赢得足够的声誉——但如果你想了解它,谷歌“不要解析xml”,第一篇文章将对此进行解释

希望这有帮助。
Jon

老实说,我想说你甚至不应该用SA/NHibernate来做这样的事情。这是一个从XML批量导入数据的过程——像SSIS这样的ETL工具将是一个更好的选择。即使是在DB服务器上手动启动的进程也会工作得更好——步骤1,将XML加载到表中,步骤2,执行UPSERT。顺便提一下,SQL 2008为UPSERT操作引入了MERGE命令,这可能很有用

我也同意Dan的评论——是否真的有必要将姓名首字母、名字和姓氏视为单独的实体?将它们视为简单字符串可以提高性能。在您的域模型中,什么指定了它们本身就是实体

如果您确实必须继续使用SA/NHibernate,请阅读以下内容:

Jimmy博客中关于批处理选择的建议应该会有很大帮助。如果您计划一次处理一批250条记录,请将所有选择作为单个NH命令执行,处理所有数据,然后将所有更新作为另一个单独的批执行(我相信您使用EntityWithTypedId和adonet.batch\u size config设置将有助于实现这一点)

最后,关于“我使用Linq解析为XML”的语句,这真的是最好的方法吗?考虑到输入文件的大小,我猜可能是这样的,但是您知道将XML文件反序列化为对象图的方法吗?因此,我不想在描述这一点的页面上发布链接,因为我还没有赢得足够的声誉——但如果你想了解它,谷歌“不要解析xml”,第一篇文章将对此进行解释

希望这有帮助。
Jon

谢谢-这是我尝试使用lookuptables作为名称时的剩余内容-我使用int而不是实际字符串作为主键。然后我意识到查找int需要很多时间,所以我用内存支付了插入效率。谢谢,这是我尝试使用lookuptables作为名称时的剩余部分,我使用int而不是实际的字符串作为主键。然后我意识到int-tak的查找
public class Author : Entity
{   
    public virtual string Initials { get; set; }
    public virtual string ForeName { get; set; }
    public virtual string LastName { get; set; }
}