2


我正在构建一个 Web 应用程序,该应用程序在其SQL数据库中搜索用户输入的查询。一个简单的搜索引擎。
让我们提议我有很多行 - 超过几千行。我想让通话更有效率。
我知道我的电话只需一个*SQL查询即可。我想知道是否Linq-To-Sql有这种优化。
我知道它Lazy用于查询。我现在无法对其进行基准测试,因为我的数据库中没有足够的数据。

    foreach(var word in words)
    {
        var niqquh = number == 666 ? "" : Languages[number];
        var S = db.Uploads.Where(w => number == 666 ? true : (w.Language == niqquh));
        if(S.Count() > 20)
            S = S.Take(20);
        S = S.OrderBy(u => (u.Tags.Contains(word) ? 15 : 0) + (u.Name.Contains(word) ? 10 : 0) + (u.Description.Contains(word) ? 5 : 0));
        listOfList.Add(S.ToList());
    }


正如你在这里看到的,我有一个“幻数” 666,用来表示“任何语言都可以”。
然后,我只想取前 20 个元素,所以我调用Count()then Take
然后,我根据我的需要对结果进行排序。关键是
,我认为lazy表达式被评估Count- 因此它不能被优化为包含该级别的前 20 行SQL Query- 但在客户端的 (ASP.NET) 级别。因此,我基本上将整个数据库下载到客户端,这很糟糕。

它是否得到优化,如果没有,我怎样才能以有效的方式做到这一点,即使我必须回到纯SQL字符串语句?

*每个查询word

4

2 回答 2

5

你是对的,它需要执行语句来获取计数。但是,您不需要检查计数。所以,改变

if(S.Count() > 20)             
    S = S.Take(20); 

S = S.Take(20); 

可以这样重写:

foreach(var word in words)
{
    var niqquh = number == 666 ? "" : Languages[number];
    var S = db.Uploads.Where(w => number == 666 || w.Language == niqquh)
        .Take(20)
        .OrderBy(u => (u.Tags.Contains(word) ? 15 : 0) + (u.Name.Contains(word) ? 10 : 0) + (u.Description.Contains(word) ? 5 : 0));
    listOfList.Add(S.ToList());
}
于 2012-07-12T19:19:05.113 回答
3
if(S.Count() > 20) 

这会运行一个查询,是的...

SELECT COUNT(*) FROM

所以你没有下载整个表。


S = S.Take(20);

这不会执行查询。它确实将(无序的)查询限制为 20 个项目。通常,您希望在限制结果之前应用订单。

如果您采取的措施不止于此,也不例外。你只会得到更少的物品。因此,不需要 Count。


S.ToList();

这会运行一个查询。


IQueryable<Upload> query = db.Uploads;
if (number != 666)
{
   var niqquh = Languages[number];
   query = query.Where(w => w.Language == niqquh);
}
query = query
  .OrderBy(u => (u.Tags.Contains(word) ? 15 : 0) + (u.Name.Contains(word) ? 10 : 0) + (u.Description.Contains(word) ? 5 : 0))
  .Take(20);
listOfList.Add(query.ToList()); 
于 2012-07-12T19:26:51.040 回答