有如下查询:其中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
重点在于select的一个字段,包含大量文本,会造成查询缓慢,解决办法是,对这个字段生成摘要,最终不查询大文本字段,而查询摘要字段。
问题跟ef没关系,是你查询优化问题.
data = data.where(predicate) .skip((pageIndex - 1)*pageSize) .take(pageSize)
肯定是这样做的.只是你的where条件没有做索引优化,所以会有问题.你看下生成的sql
主键已经建了索引。
@jackccc: 你把生成的sql贴出来.和sql执行计划贴出来.让大家给你优化下
总的来说这是个sql优化题目,不是ef使用方法题.
@吴瑞祥: sql贴出来了
@jackccc: WHERE ([Extent1].[Field1] = xxx) AND ([Extent2].[Field2] = xxx) AND (xxx = [Extent1].[Field3]) AND ([Extent1].[Field4] = @p__linq__0)条件用到的4个字段有索引吗
@吴瑞祥: 加了非聚集索引
@jackccc: 执行计划有吗?
数据量很大,请问是多大?几十亿条还是几百亿条?
题目已改。
@jackccc: 没看出来。
按照正常的写法
var q=datacontext.table.where(predicate).skip(i).take(j)
这样就很好了,很慢的话,估计你是真的太多数据了,所以问你到底是几十亿条。
刚刚刷新看到你的思路了,思路一和思路二都是错误的。你走了歪路。
如果你不能让查询变快的话,一定是哪儿出了问题。
其实很多人都乱用EF,但是如果你有机会可以访问SQL SERVER的话,打开SQL PROFILE就可以看到生成的SQL 语句,这样可以避免好多就算是多年编程经验也会出现的错误。
@爱编程的大叔: 嗯,sql贴出来了
后面一种写法是错的
我的思路是先take一个小的list出来,我在筛选这个小的list,得到我需要的数据。
@jackccc: 先take在where这样会遗漏数据。另,看你贴了sql语句,可以看下执行计划,看看cost情况
亲,不到tolist()方法,是不会访问数据库的,按照语法,是不是必须先order by主键然后take之类的操作