也记一次性能优化: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 ...
随机推荐
- uboot各文件及文件夹分析
1.配置编译 uboot的配置编译需要在linux原生文件夹下,因为在编译过程中会生成符号链接.在windows中不支持.配置方法是:首先cd进入uboot源码的根目录,然后在根目录下执行:make ...
- 双向数据绑定实现之Object.defineProperty
vue.js利用的是es5的 defineproperty 特性实现的双向数据绑定,了解一下基本原理. 举例 var person= {}; Object.defineProperty(person, ...
- 「模板」 树链剖分 HLD
「模板」 树链剖分 HLD 不懂OOP的OIer乱用OOP出人命了. 谨此纪念人生第一次类套类. 以及第一次OI相关代码打过200行. #include <algorithm> #incl ...
- Markdown 代码块中再内嵌一个行内代码
在 jQuery 1.9 之前(不含1.9):如果传入一个空字符串. null 或 jQuery.parseJSON( jsonString ) ,该函数将返回,而不是抛出一个错误,即使它不是有效的 ...
- Chrome profile manager
由于Firefox有profile manager这么一说,所以自然联想到chrome应该也有. 默认chrome的profile manager被禁止了. 1. chrome://flags 2. ...
- onCreateView的一个细节--Fragment
public View onCreateView(LayoutInflater inflater, ViewGroup contaiiner, Bundle savedInstanceState) 在 ...
- Spring 路由地址的基本使用
1.下面是spring的使用基本框架连接 https://www.cnblogs.com/HD/p/4103239.html
- 一个简单插件this传值的跟踪
<!DOCUTYPE html> <html> <head> <meta charset="UTF-8"> <script s ...
- 关于 zfs 命令相关介绍
三种设备:filesystem volume snapshot 1.zfs listroot@UA4300D-spa:~/hanhuakai/pro_07/git_0708# zfs listNA ...
- nodejs安装express以后,使用express显示不是内部或外部命令
1.问题描述 在命令窗口通过npm install -g express 安装express以后,通过express -e express新建工程失败,提示express不是内部或外部命令 2.解决方 ...