从刚刚开始接触ORM到现在已有超过八年时间,用过了不少ORM框架也了解了不少ORM框架,看过N种关于ORM框架的相关资料与评论,各种言论让人很难选择。在ORM的众多问题中最突出的问题是关于性能方面的问题,因此我在看了国外的一遍文章(Dapper vs Entity Framework vs ADO.NET Performance Benchmarking)后受到启发,在这个文章的基础上扩展了测试用例分享给大家。

模型准备

用于测试是模型是基于一个订单系统,如下图所示,主要有客户、产品、仓库、订单及订单明细。其中数据表之前的关系从图中可以看出,此外产品、订单明细是自增列,仓库是两个主键构成的复合主键表。虽然只有5张表,但是已经包含了数据表的常用情况。

数据初始化

我们使用以上代码创建数据库,初始化数据表结构,生成测试数据,生成数据量如下表所示。

 static void InitialDatabase()
{
using (var ef = new Models.EFContext())
{
if (!ef.Database.Exists())
{
ef.Database.Create(); using (var db = new Models.MegoContext())
{
db.InitialTable();
}
}
}
using (var db = new Models.MegoContext())
{
db.InitialData();
}
}
表名 说明 行数
Customers 客户表 10000
Products 产品表 9000
Warehouses 仓库表 30176
Orders 订单表 100000
OrderDetails 订单明细 600271

这些数据量已经快接近一个小型系统的数据量了,如果需要到本地执行,请将App.config文件中的连接字符串改成自己的数据库名直接运行即可。

测试用例说明

目前参与测试的框架如下:

本测试中的例子不仅仅限定于目前指定的这几种框架,这里定义了一个接口,如果想加入更多测试框架可以参考代码自行加入。

     /// <summary>
/// 性能测试项目
/// </summary>
public interface IPerformanceTest
{
/// <summary>
/// 框架名称。
/// </summary>
string Framework { get; }
/// <summary>
/// 随机获取一个客户
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
long GetCustomerById(int id);
/// <summary>
/// 随机获取一个订单的所有明细
/// </summary>
/// <param name="orderId"></param>
/// <returns></returns>
long GetDetailsByOrder(int orderId);
/// <summary>
/// 随机获取一个订单及所有明细
/// </summary>
/// <param name="orderId"></param>
/// <returns></returns>
long GetOrderAndDetails(int orderId);
/// <summary>
/// 插入离散的N个客户。
/// </summary>
/// <returns></returns>
long InsertDiscreteCustomers(Customer[] customers);
/// <summary>
/// 插入离散的N个产品,自增主键。
/// </summary>
/// <returns></returns>
long InsertDiscreteProducts(Product[] products);
/// <summary>
/// 更新离散的N个客户。
/// </summary>
/// <returns></returns>
long UpdateDiscreteCustomers(Customer[] customers);
/// <summary>
/// 删除离散的N个明细。
/// </summary>
/// <returns></returns>
long DeleteDiscreteDetails(OrderDetail[] details);
/// <summary>
/// 删除离散的N个仓库,多主键。
/// </summary>
/// <returns></returns>
long DeleteDiscreteWarehouses(Warehouse[] warehouses);
}

我们主要有如下表几项测试(输出标题用于在结果中显示):

方法名 每次的测试量 输出标题 测试说明
GetCustomerById 随机查询100次。 SELECT1 随机用主键获取指定客户数据。
GetDetailsByOrder 随机查询100次。 SELECT2 随机用订单主键获取相关的订单明细数据。
GetOrderAndDetails 随机查询100次。 SELECT3 随机用订单主键获取当前订单及所有订单明细数据。
InsertDiscreteCustomers 插入500条数据。 INSERT1 插入指定数量的客户。
InsertDiscreteProducts 插入500条数据。 INSERT2 插入指定数量的产品(产品的主键是自增列的)。
UpdateDiscreteCustomers 更新500条数据。 UPDATE 更新指定数量的客户。
DeleteDiscreteDetails 删除500条数据。 DELETE1 删除指定数量的订单明细。
DeleteDiscreteWarehouses 删除500条数据。 DELETE2 删除指定数量的仓库(仓库是复合主键)。

这里我们已经测试一个框架的增删改查,单个主键、复合主键、自增主键都有覆盖。为了公平我们将按顺序执行每个框架的测试,然后再重复执行多次,以下为测试运行代码,我们将忽略第一轮的运行结果。

List<TestResultItem> results = new List<TestResultItem>();
for (int i = ; i < TestSumCount + ; i++)
{
foreach (var framework in frameworks)
{
foreach (var p in insertProducts) p.Id = ;
var item = new TestResultItem(framework)
{
Convert.ToInt64(Enumerable.Range(,TestSelectCount1).Sum(a=>
framework.GetCustomerById(r.Next(customeIds.Item1, customeIds.Item2))
)),
Convert.ToInt64(Enumerable.Range(,TestSelectCount2).Sum(a=>
framework.GetDetailsByOrder(r.Next(orderIds.Item1, orderIds.Item2))
)),
Convert.ToInt64(Enumerable.Range(,TestSelectCount3).Sum(a=>
framework.GetOrderAndDetails(r.Next(orderIds.Item1, orderIds.Item2))
)),
framework.InsertDiscreteCustomers(insertCustomes),
framework.InsertDiscreteProducts(insertProducts),
framework.UpdateDiscreteCustomers(updateCustomes),
framework.DeleteDiscreteDetails(deleteDetails),
framework.DeleteDiscreteWarehouses(deleteWarehouse),
};
if (i > )
{
results.Add(item);
}
}
}

测试结果

如下图所示为测试的结果,本次测试针对 每个框架运行了4次,结果中首先输出了每个框架每一次的运行结果,在最后的汇总中输出了所有框架的平均用时。

结果分析

首先我们需要强调的是以上测试忽略了一些先进ORM框架的优势,例如批量插入自增列数据时,所生成的编号会返回到原对象中。从如上图的测试结果可以看出在查询方面各个框架都是比较接近的,不过会随着数据量升高这个差异会升高,在插入、更新及删除操作中就差别比较大了。主要原因是在批量提交中各个框架是逐个语句提交,还是组合批量提交的差别,这里主要是实现SQL语句的不同所产生的差异。在查询方面ADO.NET+AutoMapper是性能最高的,这个没有争议,如果有疑问可以参考开头所发的例子中,本文没有测试这个项目是因为修改操作实现不理想。

这里需要补充一下,从上面的测试结果来看SqlSugar的插入和删除比其他框架要高很多,其实这是有安全代价的,因为该框架是直接将值生成在SQL语句中的如下图所示,所以使用者需要在SQL注入方面注意一下。

后计

本文只把测试结果显示出来,没有结出任何结论,有兴趣的朋友可以从 Github 上下载代码来运行查看结果,后续还会持续更新加入更多框架进行测试。

Mego(1) - NET中主流ORM框架性能对比的更多相关文章

  1. 细数.NET 中那些ORM框架 —— 谈谈这些天的收获之一

    细数.NET 中那些ORM框架 —— 谈谈这些天的收获之一(转) ADO.NET Entity Framework        ADO.NET Entity Framework 是微软以 ADO.N ...

  2. Django中的ORM框架使用小技巧

      Django中的ORM框架使用小技巧 作者:尹正杰  版权声明:原创作品,谢绝转载!否则将追究法律责任. Django对各个数据提供了很好的支持,包括PostgreSQL,MySQL,SQLite ...

  3. [java]序列化框架性能对比(kryo、hessian、java、protostuff)

    序列化框架性能对比(kryo.hessian.java.protostuff) 简介:   优点 缺点 Kryo 速度快,序列化后体积小 跨语言支持较复杂 Hessian 默认支持跨语言 较慢 Pro ...

  4. 6 大主流 Web 框架优缺点对比:15篇前端热文回看

    摘自:http://blog.csdn.net/VhWfR2u02Q/article/details/78993079 注:以下文章,点击标题即可阅读 <6 大主流 Web 框架优缺点对比> ...

  5. sqlsugar freesql hisql 三个ORM框架性能测试对比

    hisql与目前比较流行的ORM框架性能测试对比 总体测试结果 插入记录数 hisql(耗时) sqlsugar(耗时) freesql(耗时) 5条 0.0107秒 0.0312秒 0.02675秒 ...

  6. Mysql中Union和OR性能对比

    博客已搬家,更多内容查看https://liangyongrui.github.io/ Mysql中Union和OR性能对比 在leetcode上看到一篇文章,整理一下 参考:https://leet ...

  7. Mego(2) - NET主流ORM框架分析

    接上文我们测试了各个ORM框架的性能,大家可以很直观的看到各个ORM框架与原生的ADO.NET在境删改查的性能差异.这里和大家分享下我对ORM框架的理解及一些使用经验. ORM框架工作原理 典型ORM ...

  8. 主流PHP框架性能评测 (引用)

    主要涉及到的框架有 CodeIgniter 老品牌易用性框架yaf 鸟哥用c写的php扩展,高性能框架yii 自动生成代码(gii)laravel 号称最优雅的框架swoole framework 支 ...

  9. “造轮运动”之 ORM框架系列(二)~ 说说我心目中的ORM框架

    ORM概念解析 首先梳理一下ORM的概念,ORM的全拼是Object Relation Mapping (对象关系映射),其中Object就是面向对象语言中的对象,本文使用的是c#语言,所以就是.ne ...

随机推荐

  1. 大三小学期 web前端开发的一些小经验

    1.html是页面的布局设计,就是页面上要放哪些东西,比如登录界面需要按钮,输入框等等:css是被用于使用设计部件和布局,例如哪些部件放在哪里,多宽多大,是否有边框等:js/jQuery是用于实现函数 ...

  2. RocketMQ与kafka对比(官方)

    淘宝内部的交易系统使用了淘宝自主研发的Notify消息中间件,使用Mysql作为消息存储媒介,可完全水平扩容,为了进一步降低成本,我们认为存储部分可以进一步优化,2011年初,Linkin开源了Kaf ...

  3. win7开通共享步骤

    win7开通共享步骤 2017-10-09    11:12:09 个人原创博客,允许转载,转载请注明作者及出处,否则追究法律责任 1,开通来宾账户 2,为来宾账户创建一个空密码 右键我的电脑,管理, ...

  4. 框架开发之——AngularJS+MVC+Routing开发步骤总结——5.14

    1.延续MVC的观念:包括路由映射的编写,Controller的内容,具体View页面js的分离. 2.结合AngularJS做前端,后端使用Node.Js的写法,引入MVC框架,进行快速的开发. 步 ...

  5. Redis主从集群的Sentinel配置

    http://www.cnblogs.com/LiZhiW/p/4851631.html

  6. 【Zabbix】 Zabbix表结构说明【转载】

    本文转自[https://www.cnblogs.com/shhnwangjian/p/5484352.html] 参考文[https://www.cnblogs.com/learningJAVA/p ...

  7. Loadrunner初学

    1.创建脚本 启动Vvitrual User Generator 创建脚本 因为我们选择录制页面相关的操作,则选择web(HTTP/HTML) application type 选择是录制浏览器网页还 ...

  8. Notepad++中实现Markdown语法高亮与实时预览

    Notepad ++是一个十分强大的编辑器,除了可以用来制作一般的纯文字说明文件,也十分适合编写计算机程序代码.Notepad ++不仅有语法高亮度显示,也有语法折叠功能,并且支持宏以及扩充基本功能的 ...

  9. (译文)开始学习Webpack-应用TypeScript,配置热加载和Source Map

    项目初始化:采用TypeScript 我们的版本是: $ node --version v8.5.0 $ npm --version 5.5.1 npm版本升级了,因为npm最近带来了新特性,本地会生 ...

  10. alpha冲刺第十天

    一.合照 二.项目燃尽图 三.项目进展 之前卡住的注册无法插入数据的问题解决 可以呈现多条数据内容了,首页文章内容呈现,问答界面问题内容呈现 四.明日规划 很多没有完善的,后面还是要继续整改 五.问题 ...