运用O/R Mapping技术处理数据性能并不低

 

注意:以下文章是我经过实践后写的(一些测试可能存在偏差),并总结出我对O/R Mapping的一些看法,并不能代表实际中所有情况。

        相信大家对O/R Mapping不感到陌生,运用O/R Mapping模式去开发数据库应用可以节省大量的工作量,特别是烦琐的SQL语句编写。虽然O/R Mapping有它的好处,但也有人说它不好有很大性能问题;他们认为反复地将对象和SQL之间的转换和大量的反射操作会带来很大性能问题。我觉得性能问题是相对的,对于HibernateNHibernate这样完善的O/R Mapping组件来说,它在数据操作上的性能要比我们普通开发人员写SQL语句操作数据的性能要高。对于编写代码不太严紧的开发人员来,使用好的O/R Mapping组件给系统性能上有较大的提高。

       可能有些人看了以上说法不太相信,O/R Mapping组件操作比直接SQL语句操作在运算过程多出了这么多的工作,怎么可能还会提高呢?经过实践,如果很好利用缓存机制的确能做了。

为了证实这一点,大家请看下测试结果(其中所用到O/R Mapping组件是我自己编写)测试的原理是分别用组件和SQL在页面上操作数据库,然后通过Microsoft Application Center Test来测试页面的并发数。为了证实并发数的有效性我核对了请求数和数据库插入的记录数,在整个测试过程中两者是一致的。

测试的环境

P4 2.4G,1GDDR333)内存,40G硬盘

SQLSERVER2000+SP3

Windows2003Server+sp1

.NetFrameWork1.1

测试代码一:

private void Page_Load(object sender, System.EventArgs e)

         {

              // 在此处放置用户代码以初始化页面

              Test.Entitys.User user = new Test.Entitys.User();

              user.ID = Guid.NewGuid().ToString();

              user.Name = "henry";

              user.Age = 27;

              user.Brityday = DateTime.Parse("1979-1-28");

              user.Remark ="kfc";

              using(HFSoft.Data.IDataSession session = _Container.OpenSession())

              {

                   session.Open();

                   session.Save(user);

              }

              Response.Write(user.ID);

         }

测试代码二:

private void Page_Load(object sender, System.EventArgs e)

         {

              // 在此处放置用户代码以初始化页面

              string strSQL = "insert into [User](ID,Name,Age,Brityday,Remark) Values(@p1,@p2,@p3,@p4,@p5)";

              System.Data.SqlClient.SqlParameter[] param = new System.Data.SqlClient.SqlParameter[5];

              param[0] = new System.Data.SqlClient.SqlParameter("@p1",Guid.NewGuid().ToString());

              param[1] = new System.Data.SqlClient.SqlParameter("@p2","henry");

              param[2] = new System.Data.SqlClient.SqlParameter("@p3",27);

              param[3] = new System.Data.SqlClient.SqlParameter("@p4",DateTime.Parse("1979-1-28"));

              param[4] = new System.Data.SqlClient.SqlParameter("@p5","kfc");

              System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand();

              cmd.CommandText = strSQL;

              cmd.Parameters.Add(param[0]);

              cmd.Parameters.Add(param[1]);

              cmd.Parameters.Add(param[2]);

              cmd.Parameters.Add(param[3]);

              cmd.Parameters.Add(param[4]);

              using(System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection("data source=.;initial catalog=NorthWind;user id=sa;pwd=;"))

              {

                   conn.Open();

                   cmd.Connection = conn;

                   cmd.ExecuteNonQuery();

                   conn.Close();

              }

         }

第一段测试代码看上去简洁,实际上在处理过程要比第二段测试代码多出大量的运算(熟悉O/R Mapping的人很清楚这一点)。接下来看下这两段测试代码的结果。

 

属性

 

 

 

 

(1)

(2)

 

测试类型:

动态

动态

 

浏览器同时连接数:

1

1

 

准备时间(秒):

 

 

 

测试持续时间:

00:00:05:00

00:00:05:00

 

测试迭代次数:

95,903

95,254

 

生成的详细测试结果:

 

 

 

 

 

摘要

 

 

 

 

 

(1)

(2)

 

请求总数:

95,904

95,255

 

连接总数:

95,903

95,254

 

 

 

 

 

 

每秒平均请求数:

319.68

317.52

 

首字节平均响应时间(毫秒):

1.98

1.98

 

末字节平均响应时间(毫秒):

2.03

2.03

 

每次迭代末字节平均响应时间(毫秒):

2.03

2.03

 

 

 

 

 

 

测试中的唯一请求数:

1

1

 

唯一响应代码数:

1

1

 

 

 

 

 

错误计数

 

 

 

 

 

(1)

(2)

 

HTTP:

 

 

 

DNS:

 

 

 

套接字:

 

 

 

 

 

 

 

其他网络统计数据

 

 

 

 

 

(1)

(2)

 

平均带宽(字节/秒):

444,043.52

435,323.35

 

 

 

 

 

 

发送字节数(字节):

39,502,048

39,806,190

 

接收字节数(字节):

93,711,008

90,790,815

 

 

 

 

 

 

发送字节平均速率(字节/秒):

131,673.49

132,687.30

 

接收字节平均速率(字节/秒):

312,370.03

302,636.05

 

 

 

 

 

 

连接错误数:

 

 

 

发送错误数:

 

 

 

接收错误数:

 

 

 

超时错误数:

 

 

 

 

 

 

 

响应代码

 

 

 

 

 

(1)

(2)

 

Response Code: 200 - 请求已成功完成。

 

 

计数:

95,904

95,255

 

 

 

百分比(%):

100.00

100.00

 

 

 

 

 

 

 

 

从测试结果看到,自己编写的O/R Mapping在处理数据的性能上比实际编写SQL语句操作数据要高,虽然只是一点点我没有对HibernateNHibernate过行过测试但我相信这些完善的O/R Mapping在性能上要比自己编写的好(特别在缓存机制的处理)!

对于自己编写O/R Mapping来说实现缓存机制是很有必要的,主要有两个:

一、反射信息缓存

反射信息缓存是最重要的,因为在O/R Mapping在实现对象和数据库互操作的同时要进行大量的反射操作。如果每次操作都重新创建反射信息,可想而知那性能是十分低下的。反射信息缓存可以通过hashtable实现,在内存中hashtable的操作速度是非常快的。

 

二、操作命令对象缓存

操作命令对象缓存相对来说比较复杂(效益远远没反射信息缓存高),因为缓存对象操作的线程必须是唯一的;一个缓存对象同时只能服务于一个线程,在处理上还有锁和解锁的问题。在建立缓存池的情况下也要注意,缓存池缓存操作命令对象范围越小越好,这样你就可以避免在缓存池中识别不同命令对象所带来的运算问题,缓存的数量也不是越多越好除了消耗内存还会影响查找效率。

 以上是我在写一个O/R Mapping组件的一些心得,希望对大家有帮助。有兴趣的朋友和我交流可以发邮件或MSN。迟下有时间我把操作对象缓存池的实现写一编文章。

 

 

 

posted on 2005-09-11 12:21  henry  阅读(2565)  评论(17编辑  收藏  举报

导航