NHibernate插入/查找性能

时间:2010-08-11 07:52:08

标签: nhibernate s#arp-architecture

我有几个XML文件,每个文件包含“root对象”的数据,我使用Linq to XML解析,然后创建实际的根对象,我使用NHibernate和尖锐的架构存储库来保存。我已经开始优化数据插入并管理在大约1小时40分钟内向数据库添加30000个对象。但是,这仍然太慢了。

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

根对象有几位作者:

public virtual IList<Author> Authors { get; set; }

作者有这样的结构:

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

通过使用类型ID(我通常不会这样做),我已经获得了极大的加速:

public class LastName : EntityWithTypedId<string>, IHasAssignedId<string>
    {
        public LastName()
        {
        }
        public LastName(string Id)
        {
            SetAssignedIdTo(Id);
        }
        public virtual void SetAssignedIdTo(string assignedId)
        {
            Id = assignedId;
        }
    }

我查找(并可能创建)如下:

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);
                    }

我可以改善吗?我应该使用存储过程/ HQL /纯SQL / ICriteria来执行查找吗?我可以使用某种形式的缓存来加速查找并减少IO吗? CommitChanges似乎是必要的,还是应该将所有东西都包装成一个事务?

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

非常欢迎任何反馈意见。非常感谢提前。

祝福,

基督教

2 个答案:

答案 0 :(得分:1)

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

我也同意丹的评论 - 是否真的有必要将首字母,姓名和姓氏视为单独的实体?将它们视为简单的字符串可以提高性能。您的域模型中的哪些内容指定它们本身就是实体?

如果你真的必须继续使用SA / NHibernate,请阅读: http://www.lostechies.com/blogs/jimmy_bogard/archive/2010/06/24/bulk-processing-with-nhibernate.aspx

Jimmy博客中关于批量处理SELECT的建议应该会有很多帮助。如果您计划一次处理一批250条记录,请将所有SELECT作为单个NH命令处理,处理所有数据,然后将所有更新作为另一个单一批处理(我相信您使用EntityWithTypedId和adonet.batch_size)配置设置将有助于实现)

最后 - 关于“我使用Linq to XML解析”的陈述 - 这真的是最好的方法吗?考虑到输入文件的大小,我猜它可能是,但您是否知道将XML文件反序列化为对象图的方法?所以我不会发布链接到描述这个的页面,因为我还没有获得足够的声誉 - 但如果你想阅读它,谷歌“不解析那个xml”,第一篇文章将解释它

希望这会有所帮助。 乔恩

答案 1 :(得分:0)

我要做的第一件事就是简化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; }
}