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

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

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

最新文章

  1. java并发编程学习:如何等待多个线程执行完成后再继续后续处理(synchronized、join、FutureTask、CyclicBarrier)
  2. 编辑 Ext 表格(一)——— 动态添加删除行列
  3. Request header is too large
  4. C#实现动态页面静态化
  5. URL 正则表达式
  6. 基本的TCP编程
  7. Matlab实现求a到b被c整除的个数
  8. mvc4 整合nhibernate3.0配置
  9. STM32的RTC万年历显示问题
  10. 从零开始学C++之运算符重载(三):完善String类([]、 +、 += 运算符重载)、&gt;&gt;和&lt;&lt;运算符重载
  11. struts1.x中web.xml文件的配置
  12. jquery.validate.js 一个jQuery验证格式控件
  13. Linux 基础(2)
  14. javascript模块化编程库require.js的用法
  15. OpenGL 背面剔除
  16. Python爬虫之pyquery库的基本使用
  17. Centos配置ARP和Tomcat Native
  18. Spring Boot 之 RESTfull API简单项目的快速搭建(二)
  19. Spring WebSocket教程(一)
  20. Gradle gitignore Gradle 模式 上传SVN 要忽略的文件

热门文章

  1. 跨平台sdk接入总结
  2. 覆盖的面积 HDU - 1255 (线段树-扫描线)模板提
  3. zabbix调优PPT
  4. C#学习之泛型准备
  5. HDU1711 KMP(模板题)
  6. Moodle插件开发系列——XMLDB编辑器
  7. process monitor教程汇总
  8. SpringMVC 用注解Annotation驱动的IoC功能@Autowired @Component
  9. MyBatis框架的使用及源码分析(十三) ResultSetHandler
  10. Data Mining的十种分析方法——摘自《市场研究网络版》谢邦昌教授