问题描述:
主要是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);
排序分页的话,首先 它会 根据排序 生成行号row_number,
这个row_number 只有在外围的select语句中才能访问, 所以加了一层,对row_number 进行分页处理
关键是 套一层 select 检索速度 慢的 根本不能用 ,这三个表 都是30W以上的数据,检索一次几分钟 不悲剧死了啊
@蔚蓝世界:
查看 执行计划,可能不是这个嵌套问题, 你 自己写的完整sql语句试试 执行时间。
太慢的话,可以 用存储过程,网上很多。
“其实只要在最上面的SQL语句后面加
ORDER BY `Extent1`.`UseCount` DESC LIMIT 0,5 ” 和第二种SQL的
执行计划是一样的哦
可是执行的时候, 直接加 零点几秒,嵌套select的 检索不出来
还是不行
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的 检索不出来
够简化了吧
@蔚蓝世界: TerminalCode 有没有索引
@Yu: 这两个的执行计划,应该一样的
@Yu: 不知道 MySql 怎么检索的 反正 不行
@蔚蓝世界: 把你的生成这个SQL的 EF 代码贴出来
加上了
@蔚蓝世界: 代码一步一步构建SQL是没什么问题的,你把这两种SQL分别COPY到查询分析器执行的情况怎样
@Yu: MYSQL 执行我没试过,在MSSQL中这两个SQL执行计划是一样的,执行时间也差不多的
@Yu: 我是用我的项目环境为测试的,也有5表连查的、分页等,没什么问题
@Yu: 我就是在查询器 执行的
@蔚蓝世界: 看从索引上有没有办法优化了,再不行就自己构建SQL了
@Yu: 悲剧啊,自己建sql 那 还得读数据 一个个放到属性中,那 EF不是 废了吗
@蔚蓝世界: 不知道是不是MYSQL对嵌套的Select不感冒,在MSSQL中不会有像这种情况出现
贴你的CS代码,才好分析吧~
加上了
@蔚蓝世界: 有点难看哈,改造成如下格式试试~
from t1 in db.T1 from t2 in db.T2 from t3 in db.T3 where ... orderby ... select ...
@幻天芒:
如果确实不好写出来,直接一个sql扔过去...
@Yu: 问题已经整理了
@蔚蓝世界: 改造成from的那种写法,写一句话试试~
NET群198031493