C#实体框架+;Linq-如何加速慢速查询?
这是一个与我所问的问题有关的问题,我发现了如何提高2000行左右表的查询性能。性能从10秒提高到1秒 现在,我尝试执行完全相同的查询,其中表有20000行,而查询需要30秒。我如何进一步改进它?2万排还不是一个很大的数字 我有一些可能的想法:C#实体框架+;Linq-如何加速慢速查询?,c#,linq,performance,asp.net-mvc-2,jqgrid,C#,Linq,Performance,Asp.net Mvc 2,Jqgrid,这是一个与我所问的问题有关的问题,我发现了如何提高2000行左右表的查询性能。性能从10秒提高到1秒 现在,我尝试执行完全相同的查询,其中表有20000行,而查询需要30秒。我如何进一步改进它?2万排还不是一个很大的数字 我有一些可能的想法: 可以通过取消规范化以删除连接和和来改进它 创建一个视图和查询,而不是查询和联接表 不要查询整个表,让用户先选择一些过滤器(例如A | B | C..等过滤器) 向表中添加更多索引 还有别的吗 这是一个MVC操作,对于20000行需要30秒:(参数由jq
- 可以通过取消规范化以删除连接和和来改进它
- 创建一个视图和查询,而不是查询和联接表
- 不要查询整个表,让用户先选择一些过滤器(例如A | B | C..等过滤器)
- 向表中添加更多索引
- 还有别的吗
public class ListPage
{
private IQueryable _data;
public int TotalPages { get; set; }
public int PageNumber { get; set; }
public int RecordCount { get; set; }
public void SetPageData<T>(IQueryable<T> data)
{
_data = data;
}
public IQueryable<T> Page<T>()
{
return (IQueryable<T>)_data;
}
}
公共类列表页
{
私有IQueryable_数据;
公共整型TotalPages{get;set;}
公共整数页码{get;set;}
公共int记录计数{get;set;}
公共void SetPageData(IQueryable数据)
{
_数据=数据;
}
公共可查询页面()
{
返回(IQueryable)\u数据;
}
}
GetQuery是:
public IQueryable<T> GetQuery()
{
return ObjectSet.AsQueryable();
}
public IQueryable GetQuery()
{
返回ObjectSet.AsQueryable();
}
custom.OrderBy方法由以下两个方法组成:
public static IQueryable<T> OrderBy<T>(this IQueryable<T> source,
string ordering, params object[] values)
{
return (IQueryable<T>)OrderBy((IQueryable)source, ordering, values);
}
public static IQueryable OrderBy(this IQueryable source, string ordering,
params object[] values)
{
if (source == null) throw new ArgumentNullException("source");
if (ordering == null) throw new ArgumentNullException("ordering");
ParameterExpression[] parameters = new ParameterExpression[] {
Expression.Parameter(source.ElementType, "") };
ExpressionParser parser = new ExpressionParser(parameters, ordering, values);
IEnumerable<DynamicOrdering> orderings = parser.ParseOrdering();
Expression queryExpr = source.Expression;
string methodAsc = "OrderBy";
string methodDesc = "OrderByDescending";
foreach (DynamicOrdering o in orderings)
{
queryExpr = Expression.Call(
typeof(Queryable), o.Ascending ? methodAsc : methodDesc,
new Type[] { source.ElementType, o.Selector.Type },
queryExpr, Expression.Quote(Expression.Lambda(o.Selector, parameters)));
methodAsc = "ThenBy";
methodDesc = "ThenByDescending";
}
return source.Provider.CreateQuery(queryExpr);
}
公共静态IQueryable OrderBy(此IQueryable源,
字符串排序,参数对象[]值)
{
return(IQueryable)OrderBy((IQueryable)源、顺序、值);
}
公共静态IQueryable OrderBy(此IQueryable源,字符串排序,
参数对象[]值)
{
如果(source==null)抛出新的ArgumentNullException(“source”);
if(ordering==null)抛出新的ArgumentNullException(“ordering”);
ParameterExpression[]参数=新的ParameterExpression[]{
Expression.Parameter(source.ElementType,“”)};
ExpressionParser=新的ExpressionParser(参数、顺序、值);
IEnumerable orderings=parser.ParseOrdering();
表达式queryExpr=source.Expression;
string methodAsc=“OrderBy”;
string methodDesc=“OrderByDescending”;
foreach(订单中的动态记录)
{
queryExpr=Expression.Call(
typeof(可查询),o.升序?methodAsc:methodDesc,
新类型[]{source.ElementType,o.Selector.Type},
queryExpr,Expression.Quote(Expression.Lambda(o.Selector,parameters));
methodAsc=“ThenBy”;
methodDesc=“然后按降序”;
}
返回source.Provider.CreateQuery(queryExpr);
}
我关心的是:
.Take(rows).AsQueryable()
您需要添加
AsQueryable()
这一事实向我表明,它当前是IEnumerable
,这意味着您可能在查询的错误端执行分页(通过网络带回太多数据)。如果没有GetQuery()
和自定义的OrderBy()
,就很难确定-但一如既往,首先要做的是通过跟踪分析查询。查看执行的查询和返回的数据。这可能很容易,但SQL跟踪可能就足够了。+1-还有一个鲜为人知的ObjectQuery
ext meth,名为.ToTraceString()
,它显示了要执行的SQL查询。非常方便的日志记录。很抱歉我错过了,GetQuery()
是一行:returnobjectset.AsQueryable()代码>。我将编辑并添加OrderBy()的代码-我不知道它的来源,可能在这里:linqextensions.codeplex.com/@JK-老实说,如果删除.AsQueryable()
@JK-也许?@Marc Gravell-ObjectQuery
实现IQueryable
,您只需检查代码是否有效即可ObjectQuery
是特定于EF的,因为他正在使用EF,所以他可以对ObjectQuery
执行显式转换:var trace=((ObjectQuery)query)。ToTraceString()
。他正在做ObjectSet.AsQueryable()
。如果他没有执行AsQueryable
,并且对ObjectSet
执行了一些LINQ操作,那么结果将是一个ObjectQuery
。我错了吗?对于编辑,我很困惑,当OrderBy使用非泛型代码时,它如何跳回基于泛型的代码。。。你能澄清一下吗?我是否遗漏了一些明显的内容?抱歉,我不确定您在问什么-此OrderBy()
是另一个类中定义的扩展方法。那么,GetQuery()
将返回IQueryable
(通用)GetQuery().OrderBy(sidx+“”+sord)
(使用您显示的方法)将是IQueryable
(非泛型)。AFAIK没有为非泛型定义Skip(…)
etc。。。不确定这将如何工作?这也是一个愚蠢的问题,但是否有一个为您尝试进行的排序定义的索引?这能像向数据库列添加索引一样简单吗?关于泛型与非泛型的比较,这是一个很好的问题。我不知道,但当我将鼠标悬停在.OrderBy上时,它说它是(扩展名)IQuerable
,它还说var list
是IQuerable
。ProductCode列上没有索引-据我所知,nvarchar(500)对于索引来说太大了。
public static IQueryable<T> OrderBy<T>(this IQueryable<T> source,
string ordering, params object[] values)
{
return (IQueryable<T>)OrderBy((IQueryable)source, ordering, values);
}
public static IQueryable OrderBy(this IQueryable source, string ordering,
params object[] values)
{
if (source == null) throw new ArgumentNullException("source");
if (ordering == null) throw new ArgumentNullException("ordering");
ParameterExpression[] parameters = new ParameterExpression[] {
Expression.Parameter(source.ElementType, "") };
ExpressionParser parser = new ExpressionParser(parameters, ordering, values);
IEnumerable<DynamicOrdering> orderings = parser.ParseOrdering();
Expression queryExpr = source.Expression;
string methodAsc = "OrderBy";
string methodDesc = "OrderByDescending";
foreach (DynamicOrdering o in orderings)
{
queryExpr = Expression.Call(
typeof(Queryable), o.Ascending ? methodAsc : methodDesc,
new Type[] { source.ElementType, o.Selector.Type },
queryExpr, Expression.Quote(Expression.Lambda(o.Selector, parameters)));
methodAsc = "ThenBy";
methodDesc = "ThenByDescending";
}
return source.Provider.CreateQuery(queryExpr);
}
.Take(rows).AsQueryable()