也记一次性能优化:LINQ to SQL中Contains方法的优化
距离上一篇博文更新已经两个月过去了。在此,先表一表这两个月干了些啥:
世界那么大,我也想去看看。四月份的时候,我入职了上海的一家电商公司,职位是.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方法的优化的更多相关文章
- LINQ to SQL 中 Concat、Union、Intersect、Except 方法的使用
Ø 前言 LINQ to SQL 中需要对两个或多个数据集进行操作,比如:合并.取交集等,主要使用下面四个方法,这四个方法都是 System.Linq.IQueryable<out T> ...
- linq to sql中的自动缓存(对象跟踪)
linq to sql中,对于同一个DataContext上下文环境,根据表主键选择记录时(当然这里所指的“记录”会自动转成“对象”),如果该记录已经被select过,默认情况下会被自动缓存下来,下次 ...
- LINQ TO SQL 中的join(转帖)
http://www.cnblogs.com/ASPNET2008/archive/2008/12/21/1358152.html join对于喜欢写SQL的朋友来说还是比较实用,也比较容易接受的东西 ...
- Linq to sql中使用DateDiff()
Linq to sql中使用DateDiff() 计算时间差的方法 第一种办法: from p in PurchaseLists where EntityFunctions.DiffDays(p.Cr ...
- Linq to sql中继承类映射转换问题
类型为的数据成员“Int32 VTOUID”不是类型的映射的一部分.该成员是否位于继承层次结构根节点的上方? 想躲开Linq to sql中问题限制可真是不容易: http://www.makaido ...
- Linq To Sql中实现Left Join与Inner Join使用Linq语法与lambda表达式
当前有两个表,sgroup与sgroupuser,两者通过gKey关联,而sgroup表记录的是组,而sgroupuser记录是组中的用户,因此在sgroupuser中不一定有数据.需要使用Left ...
- wcf+linq to sql中关联查询返回数据问题
前段时间准备采用wcf+nh框架开发sl程序,发现采用nh开发不适合我的中型.并且快速开发项目,所以综合考量了下,决定采用wcf+linq to sql . 但是此模式也有缺点,也是linq to s ...
- linq to sql 中增删改查
首先我先说一下,如果真的要用linq做项目的话,也会是比较方便的.已经尝试了在三层架构中应用linq to sql 比较方便. //有三个不同的数据库表,所以写法不一样 public class Li ...
- 关于Linq to Sql 中的left join 中defaultifempty的相关注意事项
在使用Linq to Sql的时候,进行两个表的左连接的时候要注意defaultifempty的使用,这个函数本来的意思即是:如果为空则使用默认值代替,默认值为 NULL ,当然也可以使用defaul ...
随机推荐
- kvm增加硬盘挂载
1.查询需要添加虚拟主机 [root@sz-kvm-110 images]# virsh list --all Id 名称 状态 ------- ...
- 杭电多校第七场-J-Sequence
题目描述 Let us define a sequence as belowYour job is simple, for each task, you should output Fn module ...
- Eclipse Support UTF-8
1. Windows > Preferences > General > Content Types, set UTF-8 as the default encoding for ...
- bzoj 1731: [Usaco2005 dec]Layout 排队布局 ——差分约束
Description 当排队等候喂食时,奶牛喜欢和它们的朋友站得靠近些.FJ有N(2<=N<=1000)头奶牛,编号从1到N,沿一条直线站着等候喂食.奶牛排在队伍中的顺序和它们的编号是相 ...
- poj 1797
2013-09-08 09:48 最大生成树,输出生成树中最短的边儿即可 或者对边儿排序,二份答案+BFS判断是否1连通N 时间复杂度都是O(NlogN)的 附最大生成树pascal代码 //By B ...
- HDP-2.6.1安装
1.首先安装HDP的Ambari仓库文件到本机的/etc/yum.repos.d/ambari.repo路径下
- rabbitmq之核心构架和原理总结(四)
前言 前面博文已经将安装配置和站点管理介绍了,现在开始正式学习rabbitmq的使用了: rabbitMQ的构架 rabbitmq作为消息队列,一条消息从发布到订阅消费的完整流程为: 消息 --> ...
- KVM初始化过程
转载:http://blog.csdn.net/dashulu/article/details/17074675 之前打算整理一下在Guest VM, KVM, QEMU中IO处理的整个流程,通过查阅 ...
- V4L2(二)虚拟摄像头驱动vivi深入分析【转】
转自:http://www.cnblogs.com/tureno/articles/6694463.html 转载于: http://blog.csdn.net/lizuobin2/article/d ...
- Linux下基本栈溢出攻击【转】
转自:http://blog.csdn.net/wangxiaolong_china/article/details/6844415 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[ ...