LINQ。帮我调整一下!

时间:2010-04-29 20:36:46

标签: c# linq linq-to-sql

我有一个导致一些超时问题的linq查询。基本上,我有一个查询返回一个有大约500,000条记录的表的前100个结果。

以下是查询:

using (var dc = CreateContext())
        {
            var accounts = string.IsNullOrEmpty(searchText)
                            ? dc.Genealogy_Accounts
                                .Where(a => a.Genealogy_AccountClass.Searchable)
                                .OrderByDescending(a => a.ID)
                                .Take(100)
                            : dc.Genealogy_Accounts
                                .Where(a => (a.Code.StartsWith(searchText)
                                            || a.Name.StartsWith(searchText))
                                            && a.Genealogy_AccountClass.Searchable)
                                .OrderBy(a => a.Code)
                                .Take(100);
            return accounts.Select(a => 
        }
    }

奇怪的是,它是导致超时的第一个linq查询。我认为通过“Take”我们不需要扫描所有500k的记录。但是,这必定是正在发生的事情。我猜测找到“可搜索”的联接正在引发这个问题。我无法对表进行非规范化...所以我想知道是否有办法重写linq查询以使其更快地返回...或者我是否应该将此查询写为存储过程(和如果是这样,它会是什么样子)。感谢。

2 个答案:

答案 0 :(得分:14)

首先,我将找出正在生成的查询(在LINQ to SQL中,您将设置登录数据上下文),然后在SQL Server Management Studio中对其进行概要分析。在那里玩它,直到找到足够快的东西(通过更改查询或添加索引),如果你不得不更改查询,请找出如何在LINQ中表示它。

我怀疑问题在于您要合并OrderByTake - 这意味着它可能需要找出所有结果,以便找出哪个前100名看起来像。 Code被编入索引吗?如果没有,请尝试索引 - 它可能帮助,允许服务器按照它们返回的顺序考虑记录,因此它可以在找到100条记录后停止。您也应该查看其他列的索引。

答案 1 :(得分:3)

Take(100)转换为“选择前100名”等。如果你的问题是一个非常庞大的结果集,那么这将有所帮助,其中返回了很多列。我敢打赌,你的问题是查询导致的表扫描。在这种情况下,.Take(100)可能没什么用处。

所以,可能的罪魁祸首就像你使用ADO.NET做SQL一样:你的Indxes 怎么样?被搜索的字段是否没有好的索引?与 使用良好索引的查询相比,这会导致性能急剧下降。添加包含CodeName的索引,看看会发生什么。由于Code,不使用Order By的索引会让您感到困扰。此外,哪个字段链接 Genealogy_Accounts Genealogy_AccountClass ?任何一张桌子都缺乏索引可能会让事情变得更糟。 (我猜一个包含 Searchable 的索引不太可能有用。)

使用SQL Profiler查看正在运行的实际查询(虽然您也可以在VS中执行此操作),并查看它在服务器上的确实有多糟糕。

问题可能是LINQ做一些愚蠢的生成查询,但情况可能并非如此。我们发现LINQ-to-SQL通常比我们做出更好的查询。 Even if it looks goofy, it's usually very efficient。您可以将SQL放在查询分析器中,并查看查询计划。然后重写SQL更加人性化,看看它是否改进了 - 我打赌它不会。我认为您仍会看到表格扫描,表明您的索引存在问题。