距离上一篇博文更新已经两个月过去了。在此,先表一表这两个月干了些啥:

  世界那么大,我也想去看看。四月份的时候,我入职了上海的一家电商公司,职位是.NET高级开发工程师。工作一个月,最大的感受是比以前小城市匆忙了许多,工作压力大了许多,开发方式更加的正规,不过各种流程也更加的繁杂细琐。在写代码的时候,一定要严谨细心,该验证参数合法性的时候验参,该抛异常的时候抛异常,该写日志的时候写日志,因为一个不小心而报黄页或者主流程无法顺利进行下去,是很没面子的事情。另外,我也更加关注代码的性能问题,开发环境和生产环境的数据量根本不是一个数量级的,也许在开发环境页面加载速度很快一旦上了产线却慢得无法忍受。

  好了,废话少说,言归正传。昨天,Leader安排了一个性能优化的任务。商家要导出订单信息,如果查询的订单时间间隔比较小,没什么问题,查询的订单时间跨度大了,就非常非常非常慢了。项目使用的ORM是LINQ to SQL,至于为什么要使用,这属于历史遗留问题了。

  有一个订单明细表,里面有数十个字段,为了简化问题,我们建一个简单的实体:

public class OrderItem
{
public string Id{ get; set; }
public string OrderId{ get; set; }//订单编号
public string ProductId{ get; set; }//商品ID
public int ProductQuantity{ get; set; }//商品数量
}

  一个方法一个方法排查,最后找到了问题的所在:

List<OrderItem> orderItems=OrderRepository.Find(orderItem=>orderIdList.Contains(orderItem.OrderId)).ToList();

  orderIdList是一个List<string>集合,存储了查询时间段内的订单编号。当订单编号的数量大于50时查询就开始变慢,大于100时就非常慢了。我在orderIdList里填充了1000个有效的订单编号,然后用SqlServer Profiler监控,发现上面一句LINQ查询表达式动态编译成SQL语句竟然花费了几十秒的时间,生成的SQL大概如下:

    SELECT Id,OrderId,ProductId,ProductQuantity
FROM OrderItems
WHERE OrderId IN (......)

  上面的SQL执行时间大约是0.7秒,已经为订单编号OrderId字段建立了索引,测试数据库里的数据大约是55万条。

    为了解决上面LINQ查询表达式动态编译成SQL耗时比较长的问题,最后决定直接执行SQL语句,并且IN查询改为JOIN查询,简单粗暴。解决方法如下:

//创建临时表SQL,存储查询时间段内的订单编号
string createSql = "CREATE TABLE #TmpOrderId(OrderId varchar(36));"; //订单编号插入SQL
string orderIds = orderIdList.Aggregate(string.Empty,(current,id) => current + ("('" + id + "'),"));
orderIds = orderIds.Remove(orderIds.LastIndexOf(','));
string insertSql = "INSERT INTO #TmpOrderId VALUES " + orderIds + ";"; //JOIN查询SQL
string joinSql = "SELECT T1.Id,T1.OrderId,T1.ProductId,T1.ProductQuantity FROM OrderItems AS T1 JOIN #TmpOrderId AS T2 ON T1.OrderId=T2.OrderId;"; //三条SQL语句要放在一个会话里执行,否则会报找不到临时表#TmpOrderId异常
IEnumerable<OrderItem> query = DataContext.ExecuteQuery<OrderItem>(createSql + insertSql + joinSql);

  最后,采用该解决方法,订单明细数据基本瞬间就查询出来了,效果拔群啊,该优化任务圆满完成。

也记一次性能优化:LINQ to SQL中Contains方法的优化的更多相关文章

  1. LINQ to SQL 中 Concat、Union、Intersect、Except 方法的使用

    Ø  前言 LINQ to SQL 中需要对两个或多个数据集进行操作,比如:合并.取交集等,主要使用下面四个方法,这四个方法都是 System.Linq.IQueryable<out T> ...

  2. linq to sql中的自动缓存(对象跟踪)

    linq to sql中,对于同一个DataContext上下文环境,根据表主键选择记录时(当然这里所指的“记录”会自动转成“对象”),如果该记录已经被select过,默认情况下会被自动缓存下来,下次 ...

  3. LINQ TO SQL 中的join(转帖)

    http://www.cnblogs.com/ASPNET2008/archive/2008/12/21/1358152.html join对于喜欢写SQL的朋友来说还是比较实用,也比较容易接受的东西 ...

  4. Linq to sql中使用DateDiff()

    Linq to sql中使用DateDiff() 计算时间差的方法 第一种办法: from p in PurchaseLists where EntityFunctions.DiffDays(p.Cr ...

  5. Linq to sql中继承类映射转换问题

    类型为的数据成员“Int32 VTOUID”不是类型的映射的一部分.该成员是否位于继承层次结构根节点的上方? 想躲开Linq to sql中问题限制可真是不容易: http://www.makaido ...

  6. Linq To Sql中实现Left Join与Inner Join使用Linq语法与lambda表达式

    当前有两个表,sgroup与sgroupuser,两者通过gKey关联,而sgroup表记录的是组,而sgroupuser记录是组中的用户,因此在sgroupuser中不一定有数据.需要使用Left ...

  7. wcf+linq to sql中关联查询返回数据问题

    前段时间准备采用wcf+nh框架开发sl程序,发现采用nh开发不适合我的中型.并且快速开发项目,所以综合考量了下,决定采用wcf+linq to sql . 但是此模式也有缺点,也是linq to s ...

  8. linq to sql 中增删改查

    首先我先说一下,如果真的要用linq做项目的话,也会是比较方便的.已经尝试了在三层架构中应用linq to sql 比较方便. //有三个不同的数据库表,所以写法不一样 public class Li ...

  9. 关于Linq to Sql 中的left join 中defaultifempty的相关注意事项

    在使用Linq to Sql的时候,进行两个表的左连接的时候要注意defaultifempty的使用,这个函数本来的意思即是:如果为空则使用默认值代替,默认值为 NULL ,当然也可以使用defaul ...

随机推荐

  1. Codeforces Round #396 (Div. 2) A B C D 水 trick dp 并查集

    A. Mahmoud and Longest Uncommon Subsequence time limit per test 2 seconds memory limit per test 256 ...

  2. springmvc不通过controller进行页面跳转

    1.controller 继承WebMvcConfigureAdapter 然后使用ViewControllerRegistry  来进行跳转

  3. PIP 批量更新改为清华这边的镜像更新

    之前pip批量更新的时候发现有些包无法更新,而且速度也特别慢,今天尝试了下清华的镜像,速度是真快 # coding=utf-8import pipfrom subprocess import call ...

  4. sql service 事务与锁

    了解事务和锁 事务:保持逻辑数据一致性与可恢复性,必不可少的利器. 锁:多用户访问同一数据库资源时,对访问的先后次序权限管理的一种机制,没有他事务或许将会一塌糊涂,不能保证数据的安全正确读写. 死锁: ...

  5. [LeetCode] 接雨水,题 Trapping Rain Water

    这题放上来是因为自己第一回见到这种题,觉得它好玩儿 =) Trapping Rain Water Given n non-negative integers representing an eleva ...

  6. Weblogic 9.2 启动时报错 javax.xml.namespace.QName

    启动Weblogic 时会报错.javax.xml.namespace.QName; local class incompatible: stream classdesc serialVersionU ...

  7. 2015/9/18 Python基础(14):函数式编程

    这篇写了忘发.现在补上. Python不是也不大可能成为一种函数式的编程语言,但是它支持许多有价值的函数式编程语言构建.也有些表现的像函数式编程机制但是从传统上也不能认为是函数式编程语言的构建.Pyt ...

  8. [USACO12MAR]摩天大楼里的奶牛Cows in a Skyscraper

    洛谷题目链接:[USACO12MAR]摩天大楼里的奶牛Cows in a Skyscraper 题目描述 A little known fact about Bessie and friends is ...

  9. 【NOIP】提高组2016 天天爱跑步

    [题意]n个点的树,有m个人同时开始走链,每一步花一秒,n个点都有观察员在ai秒观察,求每个观察员观察到的人数. [算法]树上差分(主席树||线段树合并) [题解]一个人的走链可以拆成u-lca和lc ...

  10. 【51NOD-0】1085 背包问题

    [算法]背包DP [题解]f[j]=(f[j-w[i]]+v[i]) 记得倒序(一个物品只能取一次) #include<cstdio> #include<algorithm> ...