2013-01-07 131 views
3

我使用EF 4.4.20627.0MySQL 5.6 LINQ查询性能优化,MySQL .net connector版本6.6.4LINQ到实体:

我有这样的方法,该方法生成的SQL是very very slow(需要超过1分钟)

private List<TNews> GetPagedNews(int pagenum, int pagesize, 
     AdvSearcherArgs advcArgs, string keyword) 
    { 
     var dataSrc = _dbRawDataContext.TNews.Where(x => x.Id>0); 
     if (!string.IsNullOrWhiteSpace(advcArgs.PMAC)) 
     { 
      dataSrc = dataSrc.Where(m => m.Pmac == advcArgs.PMAC); 
     } 
     if (!string.IsNullOrWhiteSpace(advcArgs.BegineDate)) 
     { 
      var begin = Convertion.ToDate(advcArgs.BegineDate); 
      var end = Convertion.ToDate(advcArgs.EndDate); 

      dataSrc = dataSrc.Where(m => m.PmacDT >=begin && m.PmacDT<end); 
     } 
     dataSrc = dataSrc.OrderByDescending(n => n.PmacDT).Skip(pagenum * pagesize). 
      Take(pagesize); 

     var cnt = dataSrc.Count(); 
     SetPagerValues(pagenum, pagesize, cnt); 

     return dataSrc.ToList(); 
    } 

的generaed这样的SQL:

SELECT 
`Project1`.* 
FROM 
(
    SELECT 
    `Extent1`.* 
    FROM `tnews` AS `Extent1` 
    WHERE (`Extent1`.`Id` > 0) 
    AND ((`Extent1`.`PmacDT` >= '2013-01-01 00:00:00 ') AND   
     (`Extent1`.`PmacDT` < '2013-01-07 00:00:00 ')) 
) AS `Project1` 
ORDER BY 
`Project1`.`PmacDT` DESC LIMIT 0,20 
/* Affected rows: 0 Found rows: 20 Warnings: 0 Duration for 1 query: 00:01:30 */ 

如果我移动order bylimit条款到支架,这将SQL very fast(成本低于1 sec):

SELECT 
`Project1`.* 
FROM 
(
    SELECT 
    `Extent1`.* 
    FROM `tnews` AS `Extent1` 
    WHERE (`Extent1`.`Id` > 0) 
    AND ((`Extent1`.`PmacDT` >= '2013-01-01 00:00:00 ') AND   
     (`Extent1`.`PmacDT` < '2013-01-07 00:00:00 ')) 
    ORDER BY 
    `PmacDT` DESC LIMIT 0,20 
) AS `Project1` 
/* Affected rows: 0 Found rows: 20 Warnings: 0 Duration for 1 query: 0.000 sec. */ 

是什么ProjectXExtent1是什么意思? 以及为什么实体框架不会将orderby * limit x,y置于真实查询之外?

sql很奇怪,绝对会让查询非常慢,我绝不会写这样的sql ......那么如何让EF生成一个CORRECT sql?

有什么建议吗?

+0

哪个实体框架,您使用哪个提供商的版本?尝试重新启动数据库并再次使用第二个查询(快速的),看看它有多快。 – flindeberg

+0

@flindeberg文件版本:'4.4.20627.0',.net连接器版本'6.6.4',我认为这是EF惹起SQL导致这个问题的方式,我不认为重新启动可以改变任何状态。所以我认为重点是我们使用LINQ的方式。 –

+0

似乎与[this]非常相似(http://stackoverflow.com/questions/14177424/why-does-entityframework-do-select-a-b-c-from-select-a-b-c-from-myview)问题。这将使@ Dominik的删除答案有效。 –

回答

1

只是一个快速猜测:Count()和ToList()都执行查询。首先执行ToList(),然后使用收到的列表获取元素的数量。

像这样:

private List<TNews> GetPagedNews(int pagenum, int pagesize, 
    AdvSearcherArgs advcArgs, string keyword) 
{ 
    var dataSrc = _dbRawDataContext.TNews.Where(x => x.Id>0); 
    if (!string.IsNullOrWhiteSpace(advcArgs.PMAC)) 
    { 
     dataSrc = dataSrc.Where(m => m.Pmac == advcArgs.PMAC); 
    } 
    if (!string.IsNullOrWhiteSpace(advcArgs.BegineDate)) 
    { 
     var begin = Convertion.ToDate(advcArgs.BegineDate); 
     var end = Convertion.ToDate(advcArgs.EndDate); 

     dataSrc = dataSrc.Where(m => m.PmacDT >=begin && m.PmacDT<end); 
    } 
    dataSrc = dataSrc.OrderByDescending(n => n.PmacDT).Skip(pagenum * pagesize). 
     Take(pagesize); 

    var myList = dataSrc.ToList(); //execute the query to an in-memory list 

    var cnt = myList.Count(); //get the count from the already exeuted query 
    SetPagerValues(pagenum, pagesize, cnt); 

    return myList; //return the list 
} 
+0

这解释了一个因子2,但不是60因子左右。 – usr

+0

@Kevin混合理论你可以让它运行并告诉它花费的时间吗?我很好奇。 – Marcel

+0

我试过了。不行 –