Nhibernate的Session和StatelessSession性能比较
Nhibernate的Session和StatelessSession性能比较
作者:Jesai
一个月入30K的大神有一天跟我说:我当年在你现在这个阶段,还在吊儿郎当呢!所以你努力吧!
有时候,一个想法就是1000秒,另一个想法只需要10秒
前言:
近段时间忙着给一个政府机关推送数据到国家数据库,数据量一共加起来有六十几万吧。这么多数据使用人工推送显然是一个不小的工作量,所以必须要使用程序来处理代码。为了方便,我们选择使用Nhibernate框架来进行CURD操作。有人大呼脑残,哈哈哈···为了方便偷懒,就是什么事情都敢做。六十几万,也算是一个大数据了吧。写程序可能才使用了三天左右的时间,然后就是跑数据。结果跑数据跑了两天多。1000条数据使用了1分钟左右。当时时间也很紧急,没有想太多。只好硬着头皮日夜加班跑数据。
这段时间回来公司有空闲,后面还要继续推送数据。于是领导就交代我一个任务,想一个跑数据更快捷的方案。
首先想到的是使用原生的ADO。但是,我又不甘心写太多代码,我在想为什么NHIBERNATE会这么慢?究竟是什么原因。查了一番资料。终于找到了可行的方案。自己顺便做了一个实验。证实此方案可行。原来是NHIBERNATE 的Session和StateLessSession这两个的原因。
测试环境:
Windows7
Access
Hibernate4
数据量:20000数据
首先看Session实现代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using NHibernate; using NHibernate.Cfg; namespace BDC.Framework { public class DataSourceFactoryStateless { private static Dictionary<string, IStatelessSession> staticSessionDictionary = new Dictionary<string, IStatelessSession>(); private static object lockObject = new object(); private const string OracleAssembly = "BDC.ZcServer"; private const string AccessAssembly = "BDC.Standard"; public static IStatelessSession GetSession<T>() where T:class { string assembly = typeof(T).Assembly.GetName().Name; IStatelessSession _session = null; bool isFind = false; if (staticSessionDictionary.Keys.Contains(assembly)) { _session = staticSessionDictionary[assembly]; isFind = true; } try { if(_session == null) { lock (lockObject) { ISessionFactory factory = null; switch (assembly) { case OracleAssembly: factory = LoadOracleConfig(); break; case AccessAssembly: factory = LoadAccessConfig(); break; default: throw new Exception("没有找到对应的程序集"); } // _session = factory.OpenSession(); _session=factory.OpenStatelessSession(); if (isFind) { staticSessionDictionary[assembly] = _session; } else { staticSessionDictionary.Add(assembly, _session); } } } return _session; }catch(Exception ex) { throw new Exception("数据库初始化失败"); } } private static ISessionFactory LoadOracleConfig() { Configuration config = new Configuration(); config.SetProperty("dialect", "NHibernate.Dialect.Oracle10gDialect"); config.SetProperty("hibernate.show_sql", "true"); config.SetProperty("connection.driver_class", "NHibernate.Driver.OracleManagedDataClientDriver"); config.SetProperty("connection.provider", "NHibernate.Connection.DriverConnectionProvider"); config.SetProperty("proxyfactory.factory_class", "NHibernate.Bytecode.DefaultProxyFactoryFactory, NHibernate"); config.SetProperty("connection.isolation", "ReadCommitted"); config.SetProperty("connection.release_mode", "auto"); config.SetProperty("adonet.batch_size", ""); config.SetProperty("current_session_context_class", "call"); config.SetProperty("cache.use_query_cache", "false"); config.AddAssembly("BDC.ZcServer"); config.SetProperty("connection.connection_string", OracleConnectionString.ConnectionString); return config.BuildSessionFactory(); } private static ISessionFactory LoadAccessConfig() { Configuration config = new Configuration(); config.SetProperty("dialect", "NHibernate.JetDriver.JetDialect, NHibernate.JetDriver"); config.SetProperty("hibernate.show_sql", "true"); config.SetProperty("connection.driver_class", "NHibernate.JetDriver.JetDriver, NHibernate.JetDriver"); config.SetProperty("connection.provider","NHibernate.Connection.DriverConnectionProvider"); config.SetProperty("proxyfactory.factory_class", "NHibernate.Bytecode.DefaultProxyFactoryFactory, NHibernate"); config.SetProperty("connection.isolation", "ReadCommitted"); config.SetProperty("connection.release_mode", "auto"); config.SetProperty("adonet.batch_size", ""); config.SetProperty("current_session_context_class", "call"); config.SetProperty("cache.use_query_cache", "false"); config.AddAssembly("BDC.Standard"); config.SetProperty("connection.connection_string", AccessConnectionString.ConnectionString); return config.BuildSessionFactory(); } } }
Session使用时间
StatelessSession实现代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using NHibernate; using NHibernate.Cfg; namespace BDC.Framework { public class DataSourceFactory { private static Dictionary<string, ISession> staticSessionDictionary = new Dictionary<string, ISession>(); private static object lockObject = new object(); private const string OracleAssembly = "BDC.ZcServer"; private const string AccessAssembly = "BDC.Standard"; public static ISession GetSession<T>() where T:class { string assembly = typeof(T).Assembly.GetName().Name; ISession _session = null; bool isFind = false; if (staticSessionDictionary.Keys.Contains(assembly)) { _session = staticSessionDictionary[assembly]; isFind = true; } try { if(_session == null) { lock (lockObject) { ISessionFactory factory = null; switch (assembly) { case OracleAssembly: factory = LoadOracleConfig(); break; case AccessAssembly: factory = LoadAccessConfig(); break; default: throw new Exception("没有找到对应的程序集"); } _session = factory.OpenSession(); if (isFind) { staticSessionDictionary[assembly] = _session; } else { staticSessionDictionary.Add(assembly, _session); } } } return _session; }catch(Exception ex) { throw new Exception("数据库初始化失败"); } } private static ISessionFactory LoadOracleConfig() { Configuration config = new Configuration(); config.SetProperty("dialect", "NHibernate.Dialect.Oracle10gDialect"); config.SetProperty("hibernate.show_sql", "true"); config.SetProperty("connection.driver_class", "NHibernate.Driver.OracleManagedDataClientDriver"); config.SetProperty("connection.provider", "NHibernate.Connection.DriverConnectionProvider"); config.SetProperty("proxyfactory.factory_class", "NHibernate.Bytecode.DefaultProxyFactoryFactory, NHibernate"); config.SetProperty("connection.isolation", "ReadCommitted"); config.SetProperty("connection.release_mode", "auto"); config.SetProperty("adonet.batch_size", ""); config.SetProperty("current_session_context_class", "call"); config.SetProperty("cache.use_query_cache", "false"); config.AddAssembly("BDC.ZcServer"); config.SetProperty("connection.connection_string", OracleConnectionString.ConnectionString); return config.BuildSessionFactory(); } private static ISessionFactory LoadAccessConfig() { Configuration config = new Configuration(); config.SetProperty("dialect", "NHibernate.JetDriver.JetDialect, NHibernate.JetDriver"); config.SetProperty("hibernate.show_sql", "true"); config.SetProperty("connection.driver_class", "NHibernate.JetDriver.JetDriver, NHibernate.JetDriver"); config.SetProperty("connection.provider","NHibernate.Connection.DriverConnectionProvider"); config.SetProperty("proxyfactory.factory_class", "NHibernate.Bytecode.DefaultProxyFactoryFactory, NHibernate"); config.SetProperty("connection.isolation", "ReadCommitted"); config.SetProperty("connection.release_mode", "auto"); config.SetProperty("adonet.batch_size", ""); config.SetProperty("current_session_context_class", "call"); config.SetProperty("cache.use_query_cache", "false"); config.AddAssembly("BDC.Standard"); config.SetProperty("connection.connection_string", AccessConnectionString.ConnectionString); return config.BuildSessionFactory(); } } }
StatelessSession使用时间
ADO执行原生SQL
using System; using System.Collections.Generic; using System.Data.OleDb; using System.Linq; using System.Text; using System.Threading.Tasks; namespace BDC.Standard { public class AccessConnectionTest { public bool AccessTest() { OleDbConnection mycon = null; OleDbCommand mycom = null; try { string strcon = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=E:\XXXXXXSXB.mdb;"; mycon = new OleDbConnection(strcon); mycom = mycon.CreateCommand(); mycon.Open(); for( int j= ; j < ; j++) { string sql = string.Format("insert into sqr(QLRDLJG,QLRDLRDH,QLRDLRMC,QLRFRDH,QLRFRMC,QLRMC,QLRTXDZ,QLRYB,QLRZJH,QLRZJZL,QXDM,YSDM,YWH,YWRDLJG,YWRDLRDH,YWRDLRMC,YWRFRDH,YWRFRMC,YWRMC,YWRTXDZ,YWRYB,YWRZJH,YWRZJZL) values('1','1','1','1','1','1','1','1','1','1','1','1',{0},'1','1','1','1','1','1','1','1','1','1') ", j); mycom.CommandText = sql; int i = mycom.ExecuteNonQuery(); } return true; } catch(Exception ex) { return false; } finally { mycom.Dispose(); mycon.Close(); } } } }
ADO执行原生SQL使用时间:
解析:综上就发现,Session效率非常低下,足足运行了1000多秒,就是23多分钟。再看后面两种方法,效率差不多。一个10秒,一个11秒。这么说,我其实还是可以偷懒的。继续使用NHIBERNATE,只需要换一个方法就可以了。那么?为什么这两个方法差别如此大呢。而且前面的方法运行一段时间会失败并抛出内存溢出异常,这是因为 Hibernate 把所有新插入的MotherCat实例在 session 级别的缓存区进行了缓存的缘故。其实不知道你们发现没有,StatelessSession 接口使用insert, update和 delete操作是操作数据库的, Session 使用save, saveOrUpdate 和delete 。区别就在Save和Insert这两个方法。
原因:使用StatelessSession(无状态 session)接口是使用流的方式来操作数据,大大提升效率。它没有持久上下文。不存在高层的生命周期。没有多级缓存,它也不管你数据的准确性,是否重复,是否存在脏数据,不级联更新数据。也不会出发Hibernate的事务和触发器等,简单的来说,就相当于一个底层的JDBC。
使用注意:它没有事务,没有缓存,没有脏数据检查。所以我们使用在系统的时候,千万要小心使用,不然会造成脏数据,污染数据库,或者导致数据不正确。而且如果系统抛异常,则是很危险的,数据是马上执行存取操作的。数据写到一半,抛个异常,这个数据就错了。而且还不会回滚。
综上,对已有数据,要求效率的时候,而且保证数据不会出现问题,异或,自己对异常,脏数据等有一套方案,可以使用NHIBERNATE的StateLessSession.不是特别追求速度的话,还是使用Session。
Nhibernate的Session和StatelessSession性能比较的更多相关文章
- NHibernate中Session的处理 线程不安全
NHibernate中Session是线程不安全的,而且每次数据库操作 请求创建Session时对性能有些影响.在Windows应用中可以通过 [ThreadStatic]特性很简单的就可以实现线程安 ...
- Nhibernate的Session管理
参考:http://www.cnblogs.com/renrenqq/archive/2006/08/04/467688.html 但这个方法还不能解决Session缓存问题,由于创建Session需 ...
- NHibernate中session.update()及session.merge()的区别
今天的工作中遇到一个奇怪的问题,如下: "a different object with the same identifier value was already associated w ...
- NHibernate 慎用Session.Merge
Session.Merge其意思有两个步骤, 一般用法: Session.Merge(obj); 1. 从当前的Session中获取obj对象, 如果未获取到则从数据库获取. 2. 把程序中的obj的 ...
- NHibernate系列文章十七:NHibernate Session管理(附程序下载)
摘要 NHibernate的Session的管理涉及到NHibernate的两个最重要的对象ISessionFactory和ISession.ISessionFactory的生成非常消耗资源,通常都在 ...
- 架构之路(九)Session Per Request
前面的两篇反应很差:没评论没赞.很伤心啊,为什么呢?搞得我好长一段时间都没更新了——呵呵,好吧,我承认,这只是我的借口.不过,还是希望大家多给反馈.没有反馈,我就只能猜了:前面两篇是不是写得太“粗”了 ...
- NHibernate系列文章二十一:延迟加载
摘要 NHibernate的延迟加载机制是很重要的内容.通过关系映射将数据库表之间的关系映射成对象之间的关系,如果没有延迟加载机制,从主表的一个对象的查询将直接查询出所有与该对象关联的其他对象,如果关 ...
- HTTP Session、Cookie机制详解
一.什么是http session,有什么用 HTTP协议本身是无状态的,本身并不能支持服务端保存客户端的状态信息,于是,Web Server中引入了session的概念,用来保存客户端的状态信息. ...
- MVC Nhibernate 示例
首先,非常感谢提出问题的朋友们,使得本人又去深入研究了NHibernate的<Session-Per-Request 模式>. 前言: 谈到NHibernate大伙并不陌生,搞Java ...
随机推荐
- 总结:关于留学网站使用laravel框架的总结
1.从git库中clone后本地项目根目录没有vendor文件夹,安装composer 2.composer install 报错 ,删除 composer.lock 文件,重新执行 composer ...
- 中和IOS七层架构和TCP/IP四层架构的五层架构
五层架构分别为应用层.运输层.网络层.数据链路层.物理层. IOS架构把应用层又细分为应用层.表示层.会话层 TCP/IP把网络层改名网际层,数据链路层和物理层结合成网络接口层 其实只要学习五层协议, ...
- Junit 测试集(打包测试)实例
测试集,直译过来的意思就是把测试集合起来,再详细一些就是把多个单元测试集合起来 .单元测试可以理解为:单个接口 或者单个类/方法 的测试 项目背景:测试基于spring开发的项目代码 实例模板:pac ...
- js中的克隆
1.如果克隆对象是基本类型,直接复制就可以 <script type="text/javascript"> var str1 = 'abc' var str2 = st ...
- childNodes和children
childNodes 返回指定元素的子节点集合,包括HTML节点,所有文本(元素之间的空格换行childNodes会看作文本节点). 通过nodeType来判断节点的类型: 元素 1 属性 2 文本 ...
- HBase的安装及使用
一.摘要以前搜书吧的数据量比较小,使用数据库+静态文件存储的方式就可以搞定,主要有2个系统组成:网站前端+后台服务.事先把图书详情等一些固定内容生成html静态文件和前端的其他静态文件打包部署,动态变 ...
- MySQL 命令行(转)
1.登录mysql 本地:mysql -u root -p, 回车后输入密码; 也可以p后不加空格,直接加密码.回车就登录了 远程:mysql -hxx.xx.xx.xx -u -pxxx 2.查看数 ...
- 微服务Dubbo和SpringCloud架构设计、优劣势比较
本文主要围绕微服务的技术选型.通讯协议.服务依赖模式.开始模式.运行模式等几方面来综合比较Dubbo和Spring Cloud 这2种开发框架.架构师可以根据公司的技术实力并结合项目的特点来选择某个合 ...
- 001 Ceph简介
一.Ceph简介 Red Hat Ceph是一个分布式的数据对象存储,系统设计旨在性能.可靠性和可扩展性上能够提供优秀的存储服务.Ceph分布式存储能够在一个统一的系统中同时提供了对象.块.和文件存储 ...
- MyBatis原理-注意点
一.${}和#{}的区别 #{}:占位符号,好处防止sql注入 ${}:sql拼接符号 动态 SQL 是 mybatis 的强大特性之一,也是它优于其他 ORM 框架的一个重要原因.mybatis 在 ...