首页新闻招聘找找看知识库
  • 回复:14 浏览:15308 2008-11-03 12:50 来自 Karron Qiu

    很多人对于ORM的性能有偏见, 认为其性能会很差. 当然在大部分情况下, 查询的性能可以根据检索策略, 延迟加载, 二级缓存等等进行调优, 这个我就不谈了, 因为有大量的文章涉及到这点. 我这篇文章, 主要是想探讨另外一个方面的性能问题, 大数据量批量操作方面的.

    对于一般有经验的ORM使用者来说, 一提到大数据量操作一般也就会说, 嗯, 这个嘛, ORM对此确实效率低下, 我们一般采用直接ADO.net. 确实是这样的. 如果是批量删除. 用ORM去做绝对是效率低下的. 那么批量插入呢? 我这边做了一个测试. 来证明使用ORM并对其进行性能调优, 有可能比直接使用SQL速度更快.

    我定义了一个简单的实体, 只有两个属性, 一个是ID, 一个是Description. ID是GUID类型. 我没有使用NH的配置文件对其进行映射, 改为使用Castle AR的attribute. 其他方面均和NH一致. 另外我定义了一个UnitOfWork的类, 用来管理session这些东西. 大家可以忽略.

    我这边只测试了插入60000条数据. 分别使用了纯粹的ADO.net, 默认情况下的NH, 以及设置了Batch_Size的NH, 最后是NH2里面最新引入的StatelessSession.

     

    测试的结果可能会给大家一个惊奇. 我的机器是 T61p, 配置为 CPUT7250, 2G RAM. 不同机器时间可能不一样.

    ADO.NET:  00:00:12.1994805

    NH: 00:00:20.0452743

    NH With Batch_Size 100: 00:00:08.8320574

    NH With StatelessSession: 00:00:04.8881699

     

    可以看到. 在默认情况下, NH插入这样简单的一个对象, 会比ADO.NET慢上许多. 耗时快2倍了. 的确很慢. 但是如果设置Batch_size为100之后, 耗时居然只有直接ADO.net的2/3. 如果使用了StatelessSession, 更是只有1/3左右.

     

    当然, 你可能会说, 我写SQL也可以进行优化, 也可以100条sql一起执行, 这样性能也会大大提高. 但是. 我们可以看到. NH的性能优化是非注入性的, 只需要调整一下配置文件即可. 而不需要对代码进行修改.  几乎所有SQL可以调优的方法, ORM基本都可以使用, 但是相对于SQL, ORM还有更多更高层次的调优方法.

     

    自此, 所谓NH的性能比直接ADO.NET慢的说法也不攻自破.

     

     

    Code

     

  • Gray Zhang
    2008-11-03 12:55 Gray Zhang
    NH的速度慢是慢在无法对SQL进行优化这一点上,比如不能指定索引,不能使用nolock方式进行select,不能选择hash join,不能使用union进行insert/update等,当然NH现在确实连select的union都不支持
    第1楼 回到顶楼
  • Karron Qiu
    2008-11-03 13:17 Karron Qiu
    你可以调整你的Criteria或者HQL让其落在某个索引上面. select union的问题可以用MultiQuery来模拟完成, 虽然不那么直接和直观. 当然, NH并不可能完全去替代SQL, 但是随着ORM的发展, 会支持越来越多的SQL的特性. 按照8,2原则, 对于企业应用软件的需求, ORM可以很好很方便完成大部分的工作, 这就够了.
    第2楼 回到顶楼
  • Gray Zhang
    2008-11-03 13:34 Gray Zhang
    真正优化性能的特性通常不是SQL标准的特性,而是各厂家延伸出来的扩展,这些我想ORM是很难支持的,不然就没有办法通用了
    第3楼 回到顶楼
  • Karron Qiu
    2008-11-03 13:40 Karron Qiu
    各种非标准的特性可以写Dialect去支持. 我就看过有人写过支持SQL Server的全文检索的Dialect.
    第4楼 回到顶楼
  • 啊文
    2008-11-04 09:57 啊文
    在一定的数量最好flush和clear
    第5楼 回到顶楼
  • Karron Qiu
    2008-11-04 10:56 Karron Qiu
    扩大batchsize, 好像不需要手工flush, 这个我没有测试过, 因为我担心手工flush会破坏batchsize的设置. 使用StatelessSession不需要clear, 或者evict, 因为他不会保留entity的状态.
    第6楼 回到顶楼
  • kiler
    2009-03-02 09:46 kiler
    高性能的话不用就行了,对于一个系统来说高性能应用毕竟是少数
    第7楼 回到顶楼
  • 鱼蛋
    2009-03-03 11:28 鱼蛋
    我想看一下lz的UnitOfWork类,能共享一下吗?
    第8楼 回到顶楼
  • riccc
    2010-10-09 17:13 riccc
    数据库负荷真的到了那种程度,还是应该采用数据归档、拆分等方案
    nh的确不支持加sql hints优化,但是他的缓存方案是比较成熟的,合理的运用缓存可以减少大量的数据库请求,对降低数据库符合很有效
    如果是自己操作数据库,需要运用缓存不容易,要考虑的方面很多
    第9楼 回到顶楼
  • kiler
    2010-10-16 14:34 kiler
    我现在有一个项目可以证明一下ORM的性能,每天插入数据2w-7w条(现在基本保持在6w每日),跑了三个月,现在主业务表总数300w条,数据库除了加索引以外,没有做任何优化,配置参数直接读取数据不做缓存。现在跑的好好的。
    第10楼 回到顶楼
  • N_unknown
    2011-08-16 22:45 N_unknown
    我又意见了哈
    你这个测试不准确

    单条插入,无异议.

    批量插入
    NH有批量插入函数,其结果是 insert.... select.... union
    如果是ado.net
    直接将 sql语句拼装成 insert.... select.... union
    你认为哪个快?
    第11楼 回到顶楼
  • 很久以前我就知道博客园的昵称可以很长很长很长很长
    你们都把SqlBulkCopy忘记了吗?
    如果是SQL2008以上还可以用表值参数,会更快。
    第12楼 回到顶楼
  • walter8098
    2013-06-06 15:51 walter8098
    第13楼 回到顶楼
登录后才能评论,请先登录注册