PetaPoco插入 - 最快的方法?

9
什么是向数据库插入记录的最快选项:使用以下哪种方式:

  • Database.Insert(poco)
  • Database.Insert(tableName, pkName, poco)
  • Database.Save(poco)
  • Database.Save(tableName, pkName, poco)

出于性能原因,我应该使用哪一个?对我来说,它们中的一个并不比另一个不方便...

谢谢。

2个回答

13
哪个方法在性能方面更好? Database.Save 方法使用 GetValue 获取主键字段的值,然后根据情况调用 Database.InsertDatabase.Update 来保存更改。
因此,只有当您的代码确实需要保存可能是新的或预先存在的对象的更改时,才应该使用 Database.Save。另外,请注意,您的表必须具有自动递增的主键列,以便 Database.Save 能够正常工作。
即使没有轻微的性能差异,我也更喜欢正确的语义 - 使用 Insert 或 Update 而不是 Save。
"其中一个对我来说并不比另一个方便..."
这并不完全正确。 Database.Insert(poco) 将在 poco 类的定义中的自定义属性中查找 tableNamepkName 的值。如果使用 T4 模板,则这些值将自动与数据库同步,并且仅在一个位置指定。另一方面,如果在每个方法调用中传递它们,则它们将在整个代码库中重复无数次。DRY。如果以后需要更改其中一个值怎么办?
现在,由于那个查找,Database.Insert(poco) 的性能会稍微降低。但是,PetaPoco 在静态字典中缓存了该查找的结果,因此在第一次查找后,性能影响将非常小:
RWLock.EnterReadLock();
PocoData pd;
try
{
    if (m_PocoDatas.TryGetValue(t, out pd))
        return pd;
}
finally
{
    RWLock.ExitReadLock();
}

是的,通过这个语句“一个对我来说并不比另一个不方便...” ,我所做的解决方法是这个:http://blogs.msmvps.com/bmains/2011/12/31/helpful-petapoco-template-modifications/ 违反了DRY原则,但根据这篇文章,这样做可以提高性能:http://www.toptensoftware.com/Articles/94/PetaPoco-More-Speed。我可能会尝试更进一步的自定义... - Brian Mains
@BrianMains:你真的有必要挤出那额外的速度吗?我曾经使用过定制的SubSonic模板一段时间(我们仍在维护的应用程序中使用它们),但这很麻烦。无论如何,我认为我已经清楚地阐述了我的答案中的权衡。你当然可以选择更快的路线而不是更容易维护的路线,但很少有用途真正需要它。最大的收益将来自批处理操作、预编译语句、适当的索引等。 - quentin-starin
1
但是您说的是500次迭代中的9毫秒左右,因此性能损失可以忽略不计。在映射代码之前,数据库将成为瓶颈。 - Schotime
@BrianMains:我在阅读你的博客文章时还注意到另一件事,就是使用你所做的修改后,你放弃了对poco多态操作的能力。例如,我在一个使用PetaPoco的项目中实现了一个UnitOfWork类,它依赖于以object的形式追踪所有变更的对象,并同时提交所有变更。显然,你可能并不需要这种能力,但要知道为了使用 Users.GetTableName() 等方法而需要知道poco类名,这是一种权衡。 - quentin-starin
@qes 感谢您从各个角度考虑这个问题。我真的很感激。是的,工作单元在许多流行的框架中都有实现,比如实体框架L2SQL、NHibernate,这是一个不错的功能。但对于大型对象图和跟踪大量更改的对象(我在EF中经历过),它可能会导致一些性能问题。在我的情况下,这是一个简单的应用程序,所有这些都是累赘。但是,对于未来阅读此帖子的人来说,这确实是需要考虑的事情。 - Brian Mains

3
在您列出的所有4种方法中,对于插入操作,看起来PetaPoco总是调用Database类的以下方法:
public object Insert(string tableName, string primaryKeyName, bool autoIncrement, object poco)

而且 Database.Insert(tableName, pkName, poco) 执行的工作最少(基本上只是一个传递方法),因此我认为它是性能最佳的方法。

这里是 Insert(string, string, object) 的代码:

public object Insert(string tableName, string primaryKeyName, object poco)
{
    return Insert(tableName, primaryKeyName, true, poco);
}

直接调用Insert(string, string, bool, object)重载可能会略微(且不易察觉地)更快。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接