首页 新闻 赞助 找找看

使用EF联合多表时遇到了一个问题

0
悬赏园豆:100 [已关闭问题] 关闭于 2014-10-16 14:05

问题描述:

主要是OrderBy前后的问题,是三个表的inner join

OrderBy之前得到的SQL:

SELECT
`Extent1`.`FavoriteCount`, 
`Extent1`.`ResId`, 
`Extent1`.`UseCount`, 
`Extent1`.`ShareCount`, 
`Extent1`.`PublishDate`, 
`Extent2`.`PasswordId`, 
`Extent1`.`ResName`, 
`Extent2`.`TerminalCode`, 
`Extent1`.`Keyword`, 
`Extent3`.`Description`, 
`Extent3`.`Author`, 
`Extent3`.`Column`
FROM `resources` AS `Extent1` 
INNER JOIN 
`specialresourcedatas` AS `Extent2` 
 ON `Extent1`.`ResId` = `Extent2`.`ResId` 
INNER JOIN 
`articles` AS `Extent3` 
 ON `Extent1`.`ResId` = `Extent3`.`ResId`
 WHERE `Extent2`.`TerminalCode` = @p__linq__0

 

这个SQL没问题。

OrderBy 并 Skip 和 Take 后

SELECT
`Project1`.`FavoriteCount`, 
`Project1`.`ResId`, 
`Project1`.`UseCount`, 
`Project1`.`ShareCount`, 
`Project1`.`PublishDate`, 
`Project1`.`PasswordId`, 
`Project1`.`ResName`, 
`Project1`.`TerminalCode`, 
`Project1`.`Keyword`, 
`Project1`.`Description`, 
`Project1`.`Author`, 
`Project1`.`Column`
FROM (SELECT
`Extent1`.`ResId`, 
`Extent1`.`ResName`, 
`Extent1`.`PublishDate`, 
`Extent1`.`Keyword`, 
`Extent1`.`FavoriteCount`, 
`Extent1`.`ShareCount`, 
`Extent1`.`UseCount`, 
`Extent2`.`TerminalCode`, 
`Extent2`.`PasswordId`, 
`Extent3`.`Column`, 
`Extent3`.`Author`, 
`Extent3`.`Description`
FROM `resources` AS `Extent1` INNER JOIN `specialresourcedatas` AS `Extent2` ON `Extent1`.`ResId` = `Extent2`.`ResId` INNER JOIN `articles` AS `Extent3` ON `Extent1`.`ResId` = `Extent3`.`ResId`
 WHERE `Extent2`.`TerminalCode` = @p__linq__0) AS `Project1`
 ORDER BY 
`Project1`.`UseCount` DESC LIMIT 0,5

 

问题来了, 为什么 rs_aJoin.OrderByDescending(u => u.UseCount) 方法后 又套了一层Select,这样性能很低

其实只要在最上面的SQL语句后面加

 ORDER BY  `Extent1`.`UseCount` DESC   LIMIT 0,5

就行了,检索非常快,可是 EF的到的SQl 运行时间几分钟,甚至超时,求大神,指点解决方法!

 

对应的C#代码

 1                 ArticleManager aMgr = new ArticleManager();
 2                 IQueryable<Resource> rRes = rMgr.LoadConditions(HttpContext.Current.Request.QueryString);//.Include(u => u.Article);
 3                 IQueryable<Article> articalRes = aMgr.LoadConditions(HttpContext.Current.Request.QueryString);
 4                 IQueryable<SpecialResourceData> srdRes=spdMgr.LoadConditions(HttpContext.Current.Request.QueryString);
 5                 //链接 终端表
 6                 var rsJsin = rRes.Join(srdRes, u => u.ResId, v => v.ResId, (u, v) => new { u.ResId, u.ResName, u.UseCount, u.FavoriteCount, u.ShareCount, u.PublishDate, u.Keyword, v.TerminalCode, v.PasswordId });
 7                 //链接文章表
 8                 var rs_aJoin = rsJsin.Join(articalRes, u => u.ResId, v => v.ResId, (u, v) => new { u.ResId, u.UseCount, u.FavoriteCount, u.ShareCount, u.PublishDate, u.PasswordId, u.ResName, u.TerminalCode,u.Keyword,v.Description, v.Author, v.Column });
 9                 //三项检索项
10                 string _SearchTerm = HttpContext.Current.Request.QueryString["SearchTerm"];
11                 if (!string.IsNullOrEmpty(_SearchTerm))
12                     rs_aJoin = rs_aJoin.Where(u => (u.Keyword.Contains(_SearchTerm) || u.ResName.Contains(_SearchTerm)) || u.Description.Contains(_SearchTerm));
13                 bool isRelation = false;
14                 IQueryable<ResourceCategory> rcRes =rcMgr.LoadConditions(HttpContext.Current.Request.QueryString,ref isRelation);
15                 IQueryable<ResourceCategoryRelation> rcrRes = rcrMgr.LoadConditions(HttpContext.Current.Request.QueryString, ref isRelation);
16                 if (isRelation)
17                 {
18                     var rrJoinTemp = rcRes.Join(rcrRes, u => u.ResCategoryId, v => v.ResCategoryId, (u, v) => new { u.CategoryOrder, u.Name, u.ResCategoryId, v.ResId });
19                     //连接 分类表
20                     rs_aJoin = rs_aJoin.Join(rrJoinTemp, u => u.ResId, v => v.ResId, (u, v) => u);//new { u.ResId, u.UseCount, u.FavoriteCount, u.PublishDate, u.ShareCount, u.PasswordId, u.ResName, u.TerminalCode, u.Author, u.Column, v.Name, v.ResCategoryId, v.CategoryOrder }
21                 }
22                var res=  rs_aJoin.OrderBy(u => u.UseCount).Skip(0)
23                         .Take(5);
大师兄石头的主页 大师兄石头 | 初学一级 | 园豆:63
提问于:2013-08-23 08:50
< >
分享
所有回答(4)
0

排序分页的话,首先 它会 根据排序 生成行号row_number,

这个row_number 只有在外围的select语句中才能访问, 所以加了一层,对row_number 进行分页处理

Qlin | 园豆:2403 (老鸟四级) | 2013-08-23 09:19

关键是 套一层 select  检索速度 慢的 根本不能用 ,这三个表 都是30W以上的数据,检索一次几分钟 不悲剧死了啊

支持(0) 反对(0) 大师兄石头 | 园豆:63 (初学一级) | 2013-08-23 09:45

@蔚蓝世界: 

查看 执行计划,可能不是这个嵌套问题, 你 自己写的完整sql语句试试 执行时间。

太慢的话,可以 用存储过程,网上很多。

支持(0) 反对(0) Qlin | 园豆:2403 (老鸟四级) | 2013-08-23 10:21
0

“其实只要在最上面的SQL语句后面加

 ORDER BY  `Extent1`.`UseCount` DESC   LIMIT 0,5 ” 和第二种SQL的

执行计划是一样的哦

Yu | 园豆:12980 (专家六级) | 2013-08-23 10:21

可是执行的时候, 直接加 零点几秒,嵌套select的 检索不出来

支持(0) 反对(0) 大师兄石头 | 园豆:63 (初学一级) | 2013-08-23 10:28

还是不行

SELECT
`Extent1`.UseCount
FROM `resources` AS `Extent1` INNER JOIN `specialresourcedatas` AS `Extent2` ON `Extent1`.`ResId` = `Extent2`.`ResId` INNER JOIN `articles` AS `Extent3` ON `Extent1`.`ResId` = `Extent3`.`ResId`
 WHERE `Extent2`.`TerminalCode` = 'pc'
 ORDER BY
`Extent1`.`UseCount` DESC LIMIT 0,5

上面的没问题

SELECT
p.UseCount
from
(SELECT
`Extent1`.UseCount
FROM `resources` AS `Extent1` INNER JOIN `specialresourcedatas` AS `Extent2` ON `Extent1`.`ResId` = `Extent2`.`ResId` INNER JOIN `articles` AS `Extent3` ON `Extent1`.`ResId` = `Extent3`.`ResId`
 WHERE `Extent2`.`TerminalCode` = 'pc'
) as p
ORDER BY
p.`UseCount` DESC LIMIT 0,5

检索不出来!

一个 零点几秒,嵌套select的 检索不出来

支持(0) 反对(0) 大师兄石头 | 园豆:63 (初学一级) | 2013-08-23 10:33

够简化了吧

支持(0) 反对(0) 大师兄石头 | 园豆:63 (初学一级) | 2013-08-23 10:34

@蔚蓝世界: TerminalCode 有没有索引

支持(0) 反对(0) Yu | 园豆:12980 (专家六级) | 2013-08-23 10:43

@Yu: 这两个的执行计划,应该一样的

支持(0) 反对(0) Yu | 园豆:12980 (专家六级) | 2013-08-23 10:49

@Yu:   不知道 MySql 怎么检索的 反正 不行

支持(0) 反对(0) 大师兄石头 | 园豆:63 (初学一级) | 2013-08-23 11:14

@蔚蓝世界: 把你的生成这个SQL的 EF 代码贴出来

支持(0) 反对(0) Yu | 园豆:12980 (专家六级) | 2013-08-23 11:36

加上了

支持(0) 反对(0) 大师兄石头 | 园豆:63 (初学一级) | 2013-08-23 13:05

@蔚蓝世界: 代码一步一步构建SQL是没什么问题的,你把这两种SQL分别COPY到查询分析器执行的情况怎样

支持(0) 反对(0) Yu | 园豆:12980 (专家六级) | 2013-08-23 13:17

@Yu: MYSQL 执行我没试过,在MSSQL中这两个SQL执行计划是一样的,执行时间也差不多的

支持(0) 反对(0) Yu | 园豆:12980 (专家六级) | 2013-08-23 13:18

@Yu: 我是用我的项目环境为测试的,也有5表连查的、分页等,没什么问题

支持(0) 反对(0) Yu | 园豆:12980 (专家六级) | 2013-08-23 13:21

@Yu: 我就是在查询器 执行的

支持(0) 反对(0) 大师兄石头 | 园豆:63 (初学一级) | 2013-08-23 15:45

@蔚蓝世界: 看从索引上有没有办法优化了,再不行就自己构建SQL了

支持(0) 反对(0) Yu | 园豆:12980 (专家六级) | 2013-08-23 16:18

@Yu: 悲剧啊,自己建sql 那 还得读数据 一个个放到属性中,那 EF不是 废了吗

支持(0) 反对(0) 大师兄石头 | 园豆:63 (初学一级) | 2013-08-23 16:35

@蔚蓝世界: 不知道是不是MYSQL对嵌套的Select不感冒,在MSSQL中不会有像这种情况出现

支持(0) 反对(0) Yu | 园豆:12980 (专家六级) | 2013-08-23 17:01
0

贴你的CS代码,才好分析吧~

幻天芒 | 园豆:37175 (高人七级) | 2013-08-23 12:59

加上了

支持(0) 反对(0) 大师兄石头 | 园豆:63 (初学一级) | 2013-08-23 13:05

@蔚蓝世界: 有点难看哈,改造成如下格式试试~

from t1 in db.T1
from t2 in db.T2
from t3 in db.T3
where ...
orderby ...
select ...
支持(0) 反对(0) 幻天芒 | 园豆:37175 (高人七级) | 2013-08-23 13:07

@幻天芒: 

如果确实不好写出来,直接一个sql扔过去...

支持(0) 反对(0) 幻天芒 | 园豆:37175 (高人七级) | 2013-08-23 13:08

@Yu:  问题已经整理了

支持(0) 反对(0) 大师兄石头 | 园豆:63 (初学一级) | 2013-08-23 15:55

@蔚蓝世界: 改造成from的那种写法,写一句话试试~

支持(0) 反对(0) 幻天芒 | 园豆:37175 (高人七级) | 2013-08-23 17:34
0

NET群198031493

SmallSnail | 园豆:216 (菜鸟二级) | 2013-08-28 16:28
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册