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

  世界那么大,我也想去看看。四月份的时候,我入职了上海的一家电商公司,职位是.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. caffe中的Accuracy+softmaxWithLoss

    转:http://blog.csdn.net/tina_ttl/article/details/51556984 今天才偶然发现,caffe在计算Accuravy时,利用的是最后一个全链接层的输出(不 ...

  2. 使用py-faster-rcnn训练VOC2007数据集时遇到问题

    使用py-faster-rcnn训练VOC2007数据集时遇到如下问题: 1. KeyError: 'chair' File "/home/sai/py-faster-rcnn/tools/ ...

  3. [转载]系统管理:update-alternatives

    http://blog.csdn.net/dbigbear/article/details/4398961 好吧,其实博主也是转载的. update-alternatives --display | ...

  4. TP-LINK TL-WN725N V2 / rtl8188eu Linux驱动安装

    https://github.com/lwfinger/rtl8188eu 驱动下载地址 安装: make all make install 参考一下把 http://devillived.net/f ...

  5. 使用 Rational AppScan 保证 Web 应用的安全性,第 1 部分: Web 安全与 Rational AppScan 入门

    前言 当今世界,Internet(因特网)已经成为一个非常重要的基础平台,很多企业都将应用架设在该平台上,为客户提供更为方便.快捷的服务支持.这些应用 在功能和性能上,都在不断的完善和提高,然而在非常 ...

  6. hive获取日期对应的星期

    pmod(datediff(order_date,'2000-01-02'),7)

  7. SpringMVC+MyBatis开发中指定callSettersOnNulls,可解决返回字段不全的问题

    Spring+MyBatis开发过程中,在xxMapper.xml配置文件进行select查询时resultType="map",如果要查询的字段是空值,在返回的map中会出现找不 ...

  8. Eclipse Support UTF-8

    1.  Windows > Preferences > General > Content Types, set UTF-8 as the default encoding for ...

  9. 编译redis时 提示make cc Command not found

    在linux系统上对redis源码进行编译时提示提示“make cc Command not found,make: *** [adlist.o] Error 127”. 这是由于系统没有安装gcc环 ...

  10. [BZOJ1177][BZOJ1178][BZOJ1179]APIO2009解题报告

    抱着好奇心态去开始做APIO的往年试题感受一下难度 Oil Description 采油区域 Siruseri政府决定将石油资源丰富的Navalur省的土地拍卖给私人承包商以建立油井.被拍卖的整块土地 ...