NhibernateSessionStatelessSession性能比较

作者: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性能比较的更多相关文章

  1. NHibernate中Session的处理 线程不安全

    NHibernate中Session是线程不安全的,而且每次数据库操作 请求创建Session时对性能有些影响.在Windows应用中可以通过 [ThreadStatic]特性很简单的就可以实现线程安 ...

  2. Nhibernate的Session管理

    参考:http://www.cnblogs.com/renrenqq/archive/2006/08/04/467688.html 但这个方法还不能解决Session缓存问题,由于创建Session需 ...

  3. NHibernate中session.update()及session.merge()的区别

    今天的工作中遇到一个奇怪的问题,如下: "a different object with the same identifier value was already associated w ...

  4. NHibernate 慎用Session.Merge

    Session.Merge其意思有两个步骤, 一般用法: Session.Merge(obj); 1. 从当前的Session中获取obj对象, 如果未获取到则从数据库获取. 2. 把程序中的obj的 ...

  5. NHibernate系列文章十七:NHibernate Session管理(附程序下载)

    摘要 NHibernate的Session的管理涉及到NHibernate的两个最重要的对象ISessionFactory和ISession.ISessionFactory的生成非常消耗资源,通常都在 ...

  6. 架构之路(九)Session Per Request

    前面的两篇反应很差:没评论没赞.很伤心啊,为什么呢?搞得我好长一段时间都没更新了——呵呵,好吧,我承认,这只是我的借口.不过,还是希望大家多给反馈.没有反馈,我就只能猜了:前面两篇是不是写得太“粗”了 ...

  7. NHibernate系列文章二十一:延迟加载

    摘要 NHibernate的延迟加载机制是很重要的内容.通过关系映射将数据库表之间的关系映射成对象之间的关系,如果没有延迟加载机制,从主表的一个对象的查询将直接查询出所有与该对象关联的其他对象,如果关 ...

  8. HTTP Session、Cookie机制详解

    一.什么是http session,有什么用 HTTP协议本身是无状态的,本身并不能支持服务端保存客户端的状态信息,于是,Web Server中引入了session的概念,用来保存客户端的状态信息. ...

  9. MVC Nhibernate 示例

    首先,非常感谢提出问题的朋友们,使得本人又去深入研究了NHibernate的<Session-Per-Request 模式>.   前言: 谈到NHibernate大伙并不陌生,搞Java ...

随机推荐

  1. 关于axios的一些封装

    关于Axios的封装 为何需要在封装 应用场景,项目中涉及100个AJAX请求,其中: 1.其中60个需要在请求头header设置token headers: {token: token}用于权限校验 ...

  2. 2018-10-17-Sublime-Text-好用的插件

    title author date CreateTime categories Sublime Text 好用的插件 lindexi 2018-10-17 10:14:40 +0800 2018-2- ...

  3. BeetleX之XRPC使用详解

    XRPC是基于BeetleX扩展一个远程接口调用组件,它提供基于接口的方式来实现远程服务调用,在应用上非常简便.组件提供.NETCore2.1和.NETStandard2.0的client版本,因此即 ...

  4. 分析CPU使用率不断增加的原因

    工程中发现引起的问题: 结合别的朋友的意见,我的优化思路是: 1.排查是否内存泄漏 经过反复查询代码,未发现有内存泄漏(可以自己百度搜索C#内存泄漏的原因).可以通过任务管理器分析是否有内存泄漏,打开 ...

  5. SpringBoot系列——启用https

    前言 有时候我们需要使用https安全协议,本文记录在SpringBoot项目启用https 生成证书 自签名证书 使用java jdk自带的生成SSL证书的工具keytool生成自己的证书 1.打开 ...

  6. $POJ2411\ Mondriaan's\ Dream$ 状压+轮廓线$dp$

    传送门 Sol 首先状压大概是很容易想到的 一般的做法大概就是枚举每种状态然后判断转移 但是这里其实可以轮廓线dp 也就是从上到下,从左到右地放方块 假设我们现在已经放到了$(i,j)$这个位置 那么 ...

  7. 如何使用CSS3中的结构伪类选择器和伪元素选择器

    结构伪类选择器介绍 结构伪类选择器是用来处理一些特殊的效果. 结构伪类选择器属性说明表 属性 描述 E:first-child 匹配E元素的第一个子元素. E:last-child 匹配E元素的最后一 ...

  8. 浅谈 OpenGL 中相关阻塞问题

    昨天我遇到一个问题,问题如下: 我使用了延迟渲染,我的渲染流程是:Pass1 --> CUDA并行计算 -->Pass2 CUDA并行计算中需要使用Pass1渲染生成的两张纹理,然而我在G ...

  9. 利用shell脚本实现每隔60秒磁盘内存数据监控脚本

    #!/bin/bash #Author:GaoHongYu #QQ: #Time:-- :: #Name:ncjk.sh #Version:V1. clear xtip=$(hostname -I) ...

  10. Docker日常常用命令汇总

    一.使用docker镜像/容器 (1)创建容器,且进入命令台 docker run --name 容器名 -i -t ubuntu /bin/bash (2)查看/容器 docker ps #查看正在 ...