首页 新闻 赞助 找找看

ef 查询执行时间过长,如何优化

0
悬赏园豆:30 [已解决问题] 解决于 2016-05-23 16:11

有如下查询:其中data为IQueryable<实体类>

data = data.Include(Expression);
data = data.OrderBy(predicate);
data = data.where(predicate)
.skip((pageIndex - 1)*pageSize)
.take(pageSize)
.tolist();

由于data数据量很大,执行where进行过滤会执行很长时间,请问如何优化此查询?

现有思路一:

data = data.skip((pageIndex - 1)*pageSize)
    .take(pageSize)
.where(predicate)
.tolist()

但这样做,可能会造成data最终的数量小于 pageSize

 

思路二:先从大的list中取前1000,然后在筛选这小的list(1000个数据)

data = data.take(1000);
data = data.where(predicate)
.skip((pageIndex - 1)*pageSize)
.take(pageSize)
.tolist()
问题补充:

EF中无法使用TakeWhile

生成的sql如

select  
[Project1].column 
...
from (
[Extent1].column
...

[Extent2].column

...

FROM[dbo].[table1]AS[Extent1]

INNER JOIN [table2] AS [Extent2] ON [Extent1].[Fieldx] = [Extent2].[Fieldx]
WHERE ([Extent1].[Field1] = xxx) AND ([Extent2].[Field2] = xxx) AND (xxx = [Extent1].[Field3]) AND ([Extent1].[Field4] = @p__linq__0)
) 
as [Project1] ORDER BY [Project1].[ID] DESC OFFSET 0 ROWS FETCH NEXT someNumber ROWS ONLY ',N'@p__linq__0 int',@p__linq__0=xxx
jackccc的主页 jackccc | 小虾三级 | 园豆:1341
提问于:2016-01-25 13:36
< >
分享
最佳答案
0

重点在于select的一个字段,包含大量文本,会造成查询缓慢,解决办法是,对这个字段生成摘要,最终不查询大文本字段,而查询摘要字段。

jackccc | 小虾三级 |园豆:1341 | 2016-05-23 16:10
其他回答(4)
0

问题跟ef没关系,是你查询优化问题.

data = data.where(predicate) .skip((pageIndex - 1)*pageSize) .take(pageSize)

肯定是这样做的.只是你的where条件没有做索引优化,所以会有问题.你看下生成的sql

收获园豆:10
吴瑞祥 | 园豆:29449 (高人七级) | 2016-01-25 13:46

主键已经建了索引。

支持(0) 反对(0) jackccc | 园豆:1341 (小虾三级) | 2016-01-25 14:12

@jackccc: 你把生成的sql贴出来.和sql执行计划贴出来.让大家给你优化下

总的来说这是个sql优化题目,不是ef使用方法题.

支持(0) 反对(0) 吴瑞祥 | 园豆:29449 (高人七级) | 2016-01-25 14:36

@吴瑞祥: sql贴出来了

支持(0) 反对(0) jackccc | 园豆:1341 (小虾三级) | 2016-01-25 15:53

@jackccc: WHERE ([Extent1].[Field1] = xxx) AND ([Extent2].[Field2] = xxx) AND (xxx = [Extent1].[Field3]) AND ([Extent1].[Field4] = @p__linq__0)条件用到的4个字段有索引吗

支持(0) 反对(0) 吴瑞祥 | 园豆:29449 (高人七级) | 2016-01-26 09:40

@吴瑞祥: 加了非聚集索引

支持(0) 反对(0) jackccc | 园豆:1341 (小虾三级) | 2016-01-26 09:52

@jackccc: 执行计划有吗?

支持(0) 反对(0) 吴瑞祥 | 园豆:29449 (高人七级) | 2016-01-26 10:06
0

数据量很大,请问是多大?几十亿条还是几百亿条?

收获园豆:10
爱编程的大叔 | 园豆:30839 (高人七级) | 2016-01-25 14:05

题目已改。

支持(0) 反对(0) jackccc | 园豆:1341 (小虾三级) | 2016-01-25 14:10

@jackccc: 没看出来。

按照正常的写法

var q=datacontext.table.where(predicate).skip(i).take(j)

这样就很好了,很慢的话,估计你是真的太多数据了,所以问你到底是几十亿条。

 

刚刚刷新看到你的思路了,思路一和思路二都是错误的。你走了歪路。

如果你不能让查询变快的话,一定是哪儿出了问题。

 

其实很多人都乱用EF,但是如果你有机会可以访问SQL SERVER的话,打开SQL PROFILE就可以看到生成的SQL 语句,这样可以避免好多就算是多年编程经验也会出现的错误。

支持(0) 反对(0) 爱编程的大叔 | 园豆:30839 (高人七级) | 2016-01-25 14:13

@爱编程的大叔: 嗯,sql贴出来了

支持(0) 反对(0) jackccc | 园豆:1341 (小虾三级) | 2016-01-25 15:55
0

后面一种写法是错的

收获园豆:5
jello chen | 园豆:7306 (大侠五级) | 2016-01-25 14:09

我的思路是先take一个小的list出来,我在筛选这个小的list,得到我需要的数据。

支持(0) 反对(0) jackccc | 园豆:1341 (小虾三级) | 2016-01-25 14:11

@jackccc: 先take在where这样会遗漏数据。另,看你贴了sql语句,可以看下执行计划,看看cost情况

支持(0) 反对(0) jello chen | 园豆:7306 (大侠五级) | 2016-01-25 17:12
0

亲,不到tolist()方法,是不会访问数据库的,按照语法,是不是必须先order by主键然后take之类的操作

收获园豆:5
张放春 | 园豆:43 (初学一级) | 2016-01-26 00:14
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册