2017-05-07 47 views
0

我创建的ASP MVC项目从大Mysql数据库获取数据〜500000LINQ和.Count之间的大数据库

我的DataTable添加到我的前端与各列的过滤器,其中只显示10个条目。

enter image description here

data = dc.books.OrderBy(x => x.id).Where(x => 
     (market_id == 0 || x.market_id == market_id) 
     && (name == null || x.name != null && (x.name.Contains(name))) 
     && (author == null || x.author != null && (x.author.Contains(author))) 
    ).Skip(param.Start).Take(10).ToList(); 

工作又好又快。

当我尝试添加计数后过滤器绑好。不工作服务器Mysql超时错误或工作非常缓慢

count = db.books.Count(x => 
        (market_id == 0 || x.market_id != 0 && x.market_id == market_id) 
        && (name == null || x.name != null && (x.name.StartsWith(name))) 

为什么计数不工作或缓慢?

所有代码我conttoller here

+0

Sql Server的计数速度非常快(还有谓词)。无论计数是否快速,它在数据库引擎中可能都是根深蒂固的。我不知道MySql,但我认为你错过了一些重要的索引。 –

回答

0

你最好这样做:

var query = db.books.AsQueryable(); 

if (market_id!=0) 
    query = query.Where(x=>x.market_id==market_id); 

if (name!=null) 
    query = query.Where(x=>x.name.StartsWith(name)); 

count = query.Count(); 
data = query 
    .OrderBy(x=>x.id) 
    .Skip(param.Start) 
    .Take(10) 
    .ToList(); 

并非所有的LINQ提供商非常好的优化了过滤器,并将它们传递到数据库。许多数据库将为这些类型的查询生成可怕的查询计划,并生成最不严重的查询计划,并将其重用于所有类似查询,这将错过使用索引的可能性使用上面的代码。

在很多情况下,你可能还需要限制算的,所以你可以这样做:

count = query.Take(1001).Count(); 

那么如果计数== 1001然后使用邮件“的超过1000个结果。”

0

这一切都归结到数据库是如何工作的,什么样的SQL被最终生成。 StartsWith被转换为通配符搜索,这可能比简单的查询慢。你可以尝试使用索引来帮助你试图优化的特定查询,并且你可以查看生成的SQL来检查它是否和你期望的一样好(有时它会产生奇怪的SQL,但是这看起来像一个简单的查询,所以我不会太担心这一点)。您可能还需要检查是否有任何区别在生成的SQL如果你加括号的或表达式的部分分开,就像name == null || (x.name != null && (x.name.StartsWith(name)))