最近一个项目,使用微软的Entity Framework的ORM框架的项目,部署到现场后,出现了系统缓慢,多个客户端的内存溢出崩溃的问题。

打开了SQL Server Profiler(SQL Server Profiler的简单使用)排查,发现有全表查询的语句,这表中有上万条数据,所以客户端查询后内存溢出了。

从代码中排查是否有直接全表查询的语句,结果未找到,后来在网上搜索到Linq to Object 连接(join) Linq to Entity时可能会引起全表查询。(https://www.cnblogs.com/gxlinhai/p/4263393.html)

所以这里也创建了一个demo做了进一步的了解。

此Demo 使用Entity Framework的ORM框架,只需要配置数据库连接,能自动生成数据库,并创建一些数据。

表有Entity和Foo两个表,其中Foo表中有Entity表的外键。

打开SQL Server Profiler检测生成的语句。

测试一,用IEnumerable来连表查询。

                IEnumerable<Foo> foos = db.Foos;
var objectNames = (from foo in foos
join en in db.Entitys
on foo.EntityId equals en.EntityId
select foo.Name).ToList();

之后在SQL Server Profiler中监测到如下语句:

SELECT
[Extent1].[EntityId] AS [EntityId],
[Extent1].[Name] AS [Name],
[Extent1].[Notes] AS [Notes]
FROM [dbo].[Entities] AS [Extent1]

出现了Entity表全表查询的语句。

测试二, 用var来连表查询。

                var foos = db.Foos;
var objectNames = (from foo in foos
join en in db.Entitys
on foo.EntityId equals en.EntityId
select foo.Name).ToList();

在SQL Server Profiler中,监测到的语句如下

SELECT
[Extent1].[Name] AS [Name]
FROM [dbo].[Foos] AS [Extent1]
INNER JOIN [dbo].[Entities] AS [Extent2] ON [Extent1].[EntityId] = [Extent2].[EntityId]

没有出现全表查询的语句。

测试三,用IQueryable来连表查询

IQueryable<Foo> foos = db.Foos;
var objectNames = (from foo in foos
join en in db.Entitys
on foo.EntityId equals en.EntityId
select foo.Name).ToList();

在SQL Server Profiler中,监测到的语句如下

SELECT
[Extent1].[Name] AS [Name]
FROM [dbo].[Foos] AS [Extent1]
INNER JOIN [dbo].[Entities] AS [Extent2] ON [Extent1].[EntityId] = [Extent2].[EntityId]

没有出现全表查询的语句。

测试四:结合别人说的代码,修改如下

 List<MyObject> objectList = new List<MyObject>();
objectList.Add(new MyObject { Identity = 1, Name = "Jack", Age = 30 });
objectList.Add(new MyObject { Identity = 2, Name = "Sam", Age = 28 });
objectList.Add(new MyObject { Identity = 3, Name = "Lucy", Age = 23 }); var objectNames = (from foo in objectList
join en in db.Entitys
on foo.Identity equals en.EntityId
select foo.Name).ToList();

在SQL Server Profiler中,监测到的语句如下

SELECT
[Extent1].[EntityId] AS [EntityId],
[Extent1].[Name] AS [Name],
[Extent1].[Notes] AS [Notes]
FROM [dbo].[Entities] AS [Extent1]

又出现了Entity全表查询的语句。

结论:

测试1:返回结果为IEnumerable时,有可能数据已经缓存到内存里了,作为了object,这样再linq查询时,不会重新调整sql语句,导致了连接表全表查询后在内存中过滤。

测试2、3: IQueryable在连表查询时,最后会重新生成sql语句来查询。var默认为DbSet,DbSet也会重新生成sql语句来查询。

测试4: 直接证明了object与linq查询,导致查询语句会变成全表查询。

Demo见如下:

百度网盘:https://pan.baidu.com/s/1cDEIS2

提取密码:qwnb

Entity Framework Code First 在Object Join Linq查询时出现全表查询的语句。的更多相关文章

  1. Entity Framework Code First 映射继承关系

    转载 http://www.th7.cn/Program/net/201301/122153.shtml Code First如何处理类之间的继承关系.Entity Framework Code Fi ...

  2. 使用 Entity Framework Code First

    使用 Entity Framework Code First 在家闲着也是闲着,继续写我的[ASP.NET MVC 小牛之路]系列吧.在该系列的上一篇博文中,在显示书本信息列表的时候,我们是在程序代码 ...

  3. Entity Framework Code First - Change Tracking

    In this post we will be discussing about change tracking feature of Entity Framework Code First. Cha ...

  4. Entity Framework Code First数据库连接

    1. 安装Entity Framework 使用NuGet安装Entity Framework程序包:工具->库程序包管理器->程序包管理器控制台,执行以下语句: PM> Insta ...

  5. Entity Framework Code First属性映射约定

    Entity Framework Code First与数据表之间的映射方式有两种实现:Data Annotation和Fluent API.本文中采用创建Product类为例来说明tity Fram ...

  6. Entity Framework Code First关系映射约定

    本篇随笔目录: 1.外键列名默认约定 2.一对多关系 3.一对一关系 4.多对多关系 5.一对多自反关系 6.多对多自反关系 在关系数据库中,不同表之间往往不是全部都单独存在,而是相互存在关联的.两个 ...

  7. Entity Framework Code First执行SQL语句、视图及存储过程

    1.Entity Framework Code First查询视图 Entity Framework Code First目前还没有特别针对View操作的方法,但对于可更新的视图,可以采用与Table ...

  8. Entity Framework Code First使用DbContext查询

    DbContext.DbSet及DbQuery是Entity Framework Code First引入的3个新的类,其中DbContext用于保持数据库会话连接,实体变化跟踪及保存,DbSet用于 ...

  9. Entity Framework Code First实体对象变动跟踪

    Entity Framework Code First通过DbContext.ChangeTracker对实体对象的变动进行跟踪,实现跟踪的方式有两种:变动跟踪快照和变动跟踪代理. 变动跟踪快照:前面 ...

随机推荐

  1. JavaScript--Dom直接选择器

    一.简介 文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标志语言的标准编程接口.在网页上,组织页面(或文档)的对象被组织在一个树形结构中,用来表示 ...

  2. python【数据类型:集合】

  3. Ansible10:Playbook的角色及包含

    目录 说明 一.Playbook的包含 1.tasks包含 2.handlers包含 3.混合包含 二.角色(roles) 1.创建role 2.引用roles 3.pre_tasks和post_ta ...

  4. ElasticStack系列之十二 & 搜索结果研究

    问题 使用 ElasticSearch 做搜索 时,比如用户输入 --> 柠檬,搜出来的结果 --> 柠檬汽水,柠檬味牙膏等在前面,真正想要的水果那个 柠檬 在后面.已经在中文分词中加了 ...

  5. css实现0.5像素的边框

    公司的设计师在做设计图的时候都是以iphone6(宽为750物理像素)为基准进行设计的.iphone6的设备像素比(即css像素与物理像素的比例)是2,所以设计师在设计图画了边框为1px的box的时候 ...

  6. bzoj千题计划134:bzoj3124: [Sdoi2013]直径

    http://www.lydsy.com/JudgeOnline/problem.php?id=3124 第一问: dfs1.dfs2 dfs2中记录dis[i]表示点i距离最长链左端点的距离 第二问 ...

  7. bzoj千题计划106:bzoj1014 [JSOI2008]火星人prefix

    http://www.lydsy.com/JudgeOnline/problem.php?id=1014 两个后缀的最长公共前缀:二分+hash 带修改带插入:splay维护 #include< ...

  8. Packet Tracer 5.0实验(一) 交换机的Telnet远程登录设置

    一.实验目标 掌握采用telnet方式配置交换机的方法 二.技术原理 配置交换机的管理IP地址(计算机的IP地址与交换机管理IP地址在同一网段): 为telnet用户配置用户名和登录口令: enabl ...

  9. JavaScript中函数和构造函数的区别

    构造函数也是函数 构造函数和其它函数的唯一区别: 构造函数是通过new操作符来调用的. 也就是说如果构造函数不用new操作符来调用,那它就是普通函数,反过来说任何函数通过new操作符来调用就可以当做构 ...

  10. Redis实战(七)Redis开发与运维

    Redis用途 1.缓存 Redis提供了键值过期时间设置, 并且也提供了灵活控制最大内存和内存溢出后的淘汰策略. 可以这么说, 一个合理的缓存设计能够为一个网站的稳定保驾护航. 2.排行榜系统 Re ...