Mego(1) - NET中主流ORM框架性能对比
从刚刚开始接触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框架性能对比的更多相关文章
- 细数.NET 中那些ORM框架 —— 谈谈这些天的收获之一
细数.NET 中那些ORM框架 —— 谈谈这些天的收获之一(转) ADO.NET Entity Framework ADO.NET Entity Framework 是微软以 ADO.N ...
- Django中的ORM框架使用小技巧
Django中的ORM框架使用小技巧 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Django对各个数据提供了很好的支持,包括PostgreSQL,MySQL,SQLite ...
- [java]序列化框架性能对比(kryo、hessian、java、protostuff)
序列化框架性能对比(kryo.hessian.java.protostuff) 简介: 优点 缺点 Kryo 速度快,序列化后体积小 跨语言支持较复杂 Hessian 默认支持跨语言 较慢 Pro ...
- 6 大主流 Web 框架优缺点对比:15篇前端热文回看
摘自:http://blog.csdn.net/VhWfR2u02Q/article/details/78993079 注:以下文章,点击标题即可阅读 <6 大主流 Web 框架优缺点对比> ...
- sqlsugar freesql hisql 三个ORM框架性能测试对比
hisql与目前比较流行的ORM框架性能测试对比 总体测试结果 插入记录数 hisql(耗时) sqlsugar(耗时) freesql(耗时) 5条 0.0107秒 0.0312秒 0.02675秒 ...
- Mysql中Union和OR性能对比
博客已搬家,更多内容查看https://liangyongrui.github.io/ Mysql中Union和OR性能对比 在leetcode上看到一篇文章,整理一下 参考:https://leet ...
- Mego(2) - NET主流ORM框架分析
接上文我们测试了各个ORM框架的性能,大家可以很直观的看到各个ORM框架与原生的ADO.NET在境删改查的性能差异.这里和大家分享下我对ORM框架的理解及一些使用经验. ORM框架工作原理 典型ORM ...
- 主流PHP框架性能评测 (引用)
主要涉及到的框架有 CodeIgniter 老品牌易用性框架yaf 鸟哥用c写的php扩展,高性能框架yii 自动生成代码(gii)laravel 号称最优雅的框架swoole framework 支 ...
- “造轮运动”之 ORM框架系列(二)~ 说说我心目中的ORM框架
ORM概念解析 首先梳理一下ORM的概念,ORM的全拼是Object Relation Mapping (对象关系映射),其中Object就是面向对象语言中的对象,本文使用的是c#语言,所以就是.ne ...
随机推荐
- java volatile关键字解析
volatile是什么 volatile在java语言中是一个关键字,用于修饰变量.被volatile修饰的变量后,表示这个变量在不同线程中是共享,编译器与运行时都会注意到这个变量是共享的,因此不会对 ...
- WEB前端中rem单位的应用(一)
在最近的开发和之前的的使用中,我们一般面对需要适应多端的项目或者需要移动端多设备的适应,都可能会引入rem,em这样的单位. 如果你要着手一个以上类似的项目,我们也同样建议使用rem或者干脆引入框架, ...
- ES6的模块化规范和CommonJS的模块化规范的差异
ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,旨在成为浏览器和服务器通用的模块解决方案.其模块功能主要由两个命令构成:export 和 import.export命令用于规定模块的对 ...
- 在eclipse中API的封装和调用
自己写的API的封装和调用:1.写好api的方法的实现类.2.抽取一个javadoc文档.file->Export->java->javadoc->finish->Yes ...
- java的枚举2
首先先理解一下java中枚举的本质. java的世界中一切皆是类,下面通过一个例子解释一下enum的本质: package cn.xnchall.enumeration; public class G ...
- cookie 使用方法
//写cookies setCookie: function(name, value) { let days = 1 let exp = new Date() exp.setTime(exp.getT ...
- python 全栈开发,Day3
python之集合,深浅copy 一.集合 集合是无序的,不重复的数据集合,它里面的元素是可哈希的(不可变类型),但是集合本身是不可哈希(所以集合做不了字典的键)的.以下是集合最重要的两点: 去重,把 ...
- Cucumber 行为驱动开发简介
Cucumber 是一个能够理解用普通语言 描述的测试用例的支持行为驱动开发(BDD)的自动化测试工具,用Ruby编写,支持Java和.Net等多种开发语言. 现在看看Cucumber中用到的术语 . ...
- PHP中文关键词匹配
关键词匹配是比较常见的需求,如留言.弹幕及游戏聊天中的敏感词过滤,都需要对一段文字进行关键词匹配.提取到关键词后,再做进一步处理. 本类借助PHP高效的数组和mbstring扩展,来实现对中文关键词的 ...
- Algorithm --> 邮票连续组合问题
邮票组合问题 有四种面值的邮票很多枚,面值分别为1,4,12,21,取五张,求取出这些邮票的最大连续组合值 代码: #include <stdio.h> #include <stri ...