NHibernate IsUpdateNecessary 需要大量时间
我的 C# 3.5 应用程序使用 SQL Server 2008 R2、NHibernate 和 CastleProject ActiveRecord。该应用程序将电子邮件及其附件导入数据库。电子邮件和附件的保存由新会话和事务范围中的 50 封电子邮件执行,以确保它们不会存储在内存中(某些邮箱中可能有 100K 电子邮件)。
最初,电子邮件保存得非常快。然而,接近 20K 封电子邮件时,性能会急剧下降。使用 dotTrace 我得到了以下图片:
显然,当我保存附件时,NHibernate 会尝试查看它是否确实应该保存它,并可能与会话中的其他附件进行比较。为此,它逐字节比较它们,这需要近 500 秒(对于图片上的快照)和 600M 枚举器操作。
所有这一切看起来都很疯狂,特别是当我确定 SaveAndFlush 确实应该保存附件而不进行任何检查时:我确定它是新的并且应该保存。
但是,我不知道如何指示 NHibernate 避免此检查(IsUpdateNecessary)。请指教。
PS 我不确定,但看起来接近 20K 的性能下降与内存中存在一些较旧的邮件无关:我注意到在我正在使用的邮箱中,较大的电子邮件比较小的电子邮件存储得晚,因此问题可能只是在附件比较中。
更新: 看起来我需要类似 StatelessSessionScope 的东西,但即使在 CastleProject 网站上也没有关于它的文档!如果我做类似的事情
using (TransactionScope txScope = new TransactionScope())
using (StatelessSessionScope scope = new StatelessSessionScope())
{
mail.Save();
}
,它会失败,但无状态会话不支持“保存”。我应该将对象插入到会话中,但我没有任何会话(只有 SessionScope,它加起来只有 SessionScope 一个接受奇怪参数的 OpenSession 方法)。
My C# 3.5 application uses SQL Server 2008 R2, NHibernate and CastleProject ActiveRecord. The application imports emails to database along with their attachments. Saving of emails and attachments is performed by 50 emails in new session and transaction scope to make sure they are not stored in memory (there can be 100K of emails in some mailbox).
Initially emails are saved very quickly. However, closer to 20K emails performance degrades dramatically. Using dotTrace I got the following picture:
Obviously, when I save an attachment, NHibernate tries to see if it really should save it and probably compares with another attachments in the session. To do so, it compares them byte by byte what takes almost 500 seconds (for the snapshot on the picture) and 600M enumerator operations.
All this looks crazy, especially when I know for sure that SaveAndFlush indeed should save the attachment without any checks: I know for sure that it is new and should be saved.
However, I cannot figure out, how to instruct NHibernate to avoid this check (IsUpdateNecessary). Please advise.
P.S. I am not sure but it might appear that degradation of performance closer to 20K is not connected with having some older mails in memory: I noticed that in mailbox I am working with, larger emails are stored later than smaller so the problem may be only in attachments comparison.
Update:
Looks like I need something like StatelessSessionScope, but there is no documentation on it even at CastleProject site! If I do something like
using (TransactionScope txScope = new TransactionScope())
using (StatelessSessionScope scope = new StatelessSessionScope())
{
mail.Save();
}
it fails with exception that Save is not supported by stateless session. I am supposed to insert objects into session, but I do not have any Session (only SessionScope, which adds up to SessionScope only single OpenSession method which accepts strange paramenters).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
也许我在那篇长文中错过了它,但是您是否使用无状态会话来导入数据?使用它可以防止大量检查并绕过一级缓存,从而使用最少的资源。
May be I missed it in that long text, but are you using stateless session for importing data? Using that prevents a lot of checks and also bypasses first level cache, thus using minimal resources.
看起来我找到了一个简单的解决方案:对于我的类附件,导致最大的性能损失,我重写了以下方法:
因此,脏检查总是认为它是脏的,并且不会进行疯狂的每字节比较。
Looks like I've found an easy solution: for my class Attachment, causing biggest performance penalty, I overridden the following method:
Thus, dirty check always consider it dirty and does not do that crazy per-byte comparison.