C#大型电商项目优化(二)——嫌弃EF与抛弃EF

上一篇博文中讲述了使用EF开发电商项目的代码基础篇,提到EF后,一语激起千层浪。不少园友纷纷表示:EF不适合增长速度飞快的互联网项目,EF只适合企业级应用等等。

也有部分高手提到了分布式,确实,性能优化从数据库出发,初期就加索引,然后垂直拆分,水平拆分,读写分离,甚至是分布式事务,阳春白雪,格局很高。然而笔者希望通过渐进的过程来优化这个项目,我们缩小格局,从细节查看不同方案的优劣。

之前提过,使用EF最主要的原因是项目时间紧迫,EF搭建速度快,熟悉的同事也多,使用方便。这个决策确实帮助我们挺过了初期的难关。在业务量增长的过程中,一些问题也逐渐暴露出来,我们开始针对问题做优化。

问题1:部分请求响应缓慢,影响用户体验。

使用EF做数据的增删改查,一些不规范代码也会拖慢程序效率,笔者在上一篇中已经提过。某些请求中可能包含多次数据查询与更新,如果这些细小的问题都以低效运行,那这个请求确实会很慢。然而在EF的框架下优化它,也未必能收到明显成效。以更新商品销量为例,我们上方案与代码:

方案1

先查出某一条数据,然后填入新算出的销量,再更新数据库,代码如下:

  //先查出数据,再更新
            var productSKU = unitOfWork.ProductSku.GetByID(dtos[0].Items[0].SKUId);
            productSKU.SalesCount = productSKU.SalesCount + dtos[0].Items[0].Quantity;
            unitOfWork.ProductSku.Update(productSKU);
            unitOfWork.Submit();

其响应时间如图:

方案2

采用IQuryable,之前提到过,这种查询方式不会真的将全部数据加载到内存,代码如下:

//2采用IQueryable查询更新
            var productSKU1 = unitOfWork.ProductSku.Get(p => p.Id == dtos[0].Items[0].SKUId);
            foreach (var item in productSKU1)
            {
                item.SalesCount = item.SalesCount + dtos[0].Items[0].Quantity;
                unitOfWork.ProductSku.Update(item);
            }
            unitOfWork.Submit();

其响应时间如图:

方案3

直接使用SQL,简单粗暴,代码如下:

//3直接使用sql更新
            string updateSql = @"update ProductSKU set SalesCount=SalesCount+" + dtos[0].Items[0].Quantity + " where Id=‘" + dtos[0].Items[0].SKUId.ToString() + "‘";
            unitOfWork.ProductSku.ExecuteSqlCommand(updateSql);
            unitOfWork.Submit();

其响应时间如图:

我们来分析下这三种方案:

方案1简单易懂,将数据查出来,更新后再塞回数据库,逻辑清晰,代码更清晰。可是将数据取出来,加载到内存,再对内存里的数据进行修改,最后生成SQL送回数据库执行,这套走下来,好像兜了一大圈,其实我们只想更新个销量。

方案2显得好了些,使用了我们在前一篇中讲到的理念,不将数据整个加载到内存,只到用时才加载,通过这种方式更新,其实生成的SQL和直接执行SQL差不太多了,但是我们可以发现:方案2和方案1时间差不多。在笔者预期中,方案2应该是比方案1好的,至于时间差不多的原因,应该是方案2用了一次循环,第二次循环时不符合条件,然后跳出循环,造成了些许时间浪费。如果是批量更新销量,方案2必然比方案1优秀很多。

方案3自然是简单粗暴,一条SQL搞定,毫不拖泥带水,其效果也是喜人的,几乎比方案1快1倍!

之前有园友提到索引的问题,其实我厂有专职DBA,不仅为数据量较大的表添加了聚集索引和非聚集索引,还写了定时任务去更新索引。所以索引这块我们不深究。

早起追逐开发效率阶段,我们可能将方案1优化为方案2,然后继续做新功能开发。但是现在我们有更多的选择,我们也有更多的时间去深究用户体验与系统效率了,那么自然的,我们开始嫌弃EF了。但是开发到这个程度,再去更换框架似乎不合适。而且大道至简,如果能用SQL搞定,那必是极好的。于是乎,我们开始对关键部分业务代码做重构,替换为原生SQL。这似乎是抛弃EF的开端。

问题2:部分数据量很大的表需要分表,EF难以维系

EF是ORM框架,映射数据库对象,然而同一数据库的一张表被拆分为两张以上,EF似乎没法映射了,两张表字段完全一致,难道再写个Model?而且分表是个动态的过程,也许一年分一次,也许一个月分一次,而且可能是定时任务去执行的,总不能一分表就改代码。自此,我们和EF的矛盾激化了。

园子里有关于数据库拆分的博客,我们所要改的只有数据访问层,最好不要动业务层。而且我们上文也提到:用原生SQL。那么我们就用原生SQL重写数据访问。

这里举个例子,比如我们拆分订单表,按年拆分,通常用户只会查看当年的订单,所以主表的查询次数肯定比其他分出的表要多,如果有用户要查往年的订单,我们再将查询范围扩大。按照这样的理念,我们开始重写数据访问层,并按照以下要点执行:

1.使用原生SQL

2.添加日期参数,如果日期超出主表的范围,则开始连接查询

3.查询中也可以添加其他条件,将参数作为对象填入SQL

4.抽象出一个生成SQL的公共方法,方便大家调用

拼装SQL是一件极其考验基本功的事,这个公共方法是我厂一位大师级的数据专家抽象出来的,大家也可以按照这个思路尝试下,一个简化版是很容易做出来的。

至此,项目中重要的业务功能已经和EF脱离关系了,我们也欣喜地收获了SQL带来的效率。而其他功能模块中,没有高并发场景或并不常用的应用,我们并没有做重构。

尽管本文标题是嫌弃,但如果是企业级应用,需要兼顾开发效率,且没有互联网模式下的业务量激增状况,笔者仍然推荐使用EF。

时间: 2024-10-26 11:15:19

C#大型电商项目优化(二)——嫌弃EF与抛弃EF的相关文章

C#大型电商项目优化(三)——扩展性与支付

上一篇文章引来不少非议,笔者并非对EF有看法,而是针对不同的业务场景和框架背景,挑选不同的方案.每个方案都有其优势劣势,挑选最快速,最简单的方案,是笔者的初衷. 看评论也是学习的过程,然而有些只做评价,却不道明原委的评论,也确实让笔者感受到了些许来自世界的恶意^_^ 开个玩笑,下面进入正题,之前系统的支付部分只需要支持支付宝和财付通,且支付代码是写在一个页面文件里的,也就是说,这个页面文件包含了支付宝和财付通的支付请求.支付同步回调和异步回调.且不说代码混乱可读性差,其可扩展性也实在不敢恭维.其

C# 大型电商项目性能优化(一)

经过几个月的忙碌,我厂最近的电商平台项目终于上线,期间遇到的问题以及解决方案,也可以拿来和大家多做交流了. 我厂的项目大多采用C#.net,使用逐渐发展并流行起来的EF(Entity Framework)框架,并搭配使用丹麦的一款主打CMS, DMS的.net web应用程序sitecore. 本篇为基础篇,侧重于阐述编码规范和一些编码技巧对系统性能的影响.不规范的编码方式,可能对单个方法或模块产生的性能影响是微不足道的,但在大型电商项目中,高并发的场景随处可见,欠妥的编码方式,可能会对整个系统

java架构师课程、性能调优、高并发、tomcat负载均衡、大型电商项目实战、高可用、高可扩展、数据库架构设计、Solr集群与应用、分布式实战、主从复制、高可用集群、大数据

15套Java架构师详情 * { font-family: "Microsoft YaHei" !important } h1 { background-color: #006; color: #FF0 } 15套java架构师.集群.高可用.高可扩展.高性能.高并发.性能优化.Spring boot.Redis.ActiveMQ.Nginx.Mycat.Netty.Jvm大型分布式项目实战视频教程 视频课程包含: 高级Java架构师包含:Spring boot.Spring  clo

Java从入门到架构师|高并发|高性能|高可用|分布式|性能调优|设计模式|大型电商项目

没有设计的思想,你就不能成为一名架构师.架构师是一个能撸的了一手好代码,画的了一个漂亮的UML/原型,写的了一篇技术文档,更加能解决好项目关键技术的综合人才.架构师=前端工程师+后端程序员+系统分析师+关键技术解决+各种技术搭配+设计模式+部署调优+其他,可见架构师是多面手,在项目当中起到连接管理与项目成员的重要角色.因此,在通往大神级的架构师的道路上,你需要懂需求.设计.代码.部署.架构.服务器.运维.调优等等. 简单系统架构图 一个能担负起企业级应用的架构师,脑海里常出现的词会是这些:负载均

16套java架构师,高并发,高可用,高性能,集群,大型分布式电商项目实战视频教程

16套Java架构师,集群,高可用,高可扩展,高性能,高并发,性能优化,设计模式,数据结构,虚拟机,微服务架构,日志分析,工作流,Jvm,Dubbo ,Spring boot,Spring cloud, Redis,ActiveMQ,Nginx,Mycat,Netty,Jvm,Mecached,Nosql,Spring,大型分布式项目实战视频教程 视频课程包含: 高级Java架构师包含:架构师,高并发,分布式,集群,高可用,高可扩展,高性能,设计模式,数据结构算法,虚拟机,微服务架构,日志分析,

企业级电商项目P2P金融项目实战,企业架构师培训视频课程

15套java架构师.集群.高可用.高可扩 展.高性能.高并发.性能优化.Spring boot.Redis.ActiveMQ.Nginx.Mycat.Netty.Jvm大型分布 式项目实战视频教程 视频课程包含: 高级Java架构师包含:Spring boot.Spring  cloud.Dubbo.Redis.ActiveMQ.Nginx.Mycat. Spring.MongoDB.ZeroMQ.Git.Nosql.Jvm.Mecached.Netty.Nio.Mina.性能调优.高并发.

大型电商分布式网站架构设计与实践,Java分布式架构,Java事务分布式高并发-视频教程

15套java架构师.集群.高可用.高可扩 展.高性能.高并发.性能优化.Spring boot.Redis.ActiveMQ.Nginx.Mycat.Netty.Jvm大型分布 式项目实战视频教程 视频课程包含: 高级Java架构师包含:Spring boot.Spring  cloud.Dubbo.Redis.ActiveMQ.Nginx.Mycat. Spring.MongoDB.ZeroMQ.Git.Nosql.Jvm.Mecached.Netty.Nio.Mina.性能调优.高并发.

柯南君:教你如何对待大型电商平台的性能优化?之 一 (方法、指标、工具、定位)

柯南君:教你如何对待大型电商平台的性能优化?之 一 (方法.指标.工具.定位) 柯南君的朋友"闲哥"最近遇到了点困扰---"大型网站平台如何对待性能优化,以及如何针对性调优?",柯南君今天,想谈一下性能优化的战略,主要是一些企业架构级别的技术和方法.柯南君将自己的个人经验和各家公司大咖的经验一起汇总给大家,如有瑕疵,请大家及时指正. 柯南君有句自律的口头语"如果你不能成为一个追求性能的疯子,那么性能将会把你变成疯子"        序曲: 如何评

大型电商互联网性能优化案例

大型电商互联网性能优化案例 理论基础 The Theory 平台设计 Platform Design 业务结果 Business Impact 双11优化 架构思考 Architecture Takeaways   ----------------------------------------------------------------------------------------------------------------------------------------------