如何通过Contains()优化Entity Framework查询的方法?

3

我们从数据库中加载大型对象图。 查询包含许多包含和使用Contains()来过滤最终结果的Where()。 Contains()用于包含大约一千个条目的集合。

性能分析器显示了庞大的难以阅读的SQL语句。 由于Contains(),无法预编译查询。

是否有优化这类查询的方法?

更新

public List<Vulner> GetVulnersBySecurityObjectIds(int[] softwareIds, int[] productIds)
        {
            var sw = new Stopwatch();

            var query = from vulner in _businessModel.DataModel.VulnerSet
                        join vt in _businessModel.DataModel.ObjectVulnerTieSet.Where(ovt => softwareIds.Contains(ovt.SecurityObjectId))
                        on vulner.Id equals vt.VulnerId
                        select vulner;

            var result = ((ObjectQuery<Vulner>)query.OrderBy(v => v.Id).Distinct())
                .Include("Descriptions")
                .Include("Data")
                .Include("VulnerStatuses")
                .Include("GlobalIdentifiers")
                .Include("ObjectVulnerTies")
                .Include("Object.ProductObjectTies.Product")
                .Include("VulnerComment");

            //Если переданы конкретные продукты, добавляем фильтрацию
            if (productIds.HasValues())
                result = (ObjectQuery<Vulner>)result.Where(v => v.Object.ProductObjectTies.Any(p => productIds.Contains(p.ProductId)));

            sw.Start();
            var str = result.ToTraceString();
            sw.Stop();
            Debug.WriteLine("Сборка запроса заняла {0} секунд.", sw.Elapsed.TotalSeconds);
            sw.Restart();
            var list = result.ToList();
            sw.Stop();
            Debug.WriteLine("Получение уязвимостей заняло {0} секунд.", sw.Elapsed.TotalSeconds);

            return list;
        }

也许吧,但是我需要看一下你想要做什么的例子才行... - PinnyM
明天就行。代码留在办公室 =) - Pavel Voronin
我认为这里使用了 like '%%',可以通过在 SQL 中对该列进行全文索引来进行优化。 - undefined
1
提高“Contains”性能的解决方案是将“softwareIds”集合分成较小的块,并执行多个查询:https://dev59.com/Wmsz5IYBdhLWcg3wcXXF#7936350 - Slauma
1个回答

2
几乎可以确定将查询拆分成多个部分会更好,尽管需要进行更多的数据库往返。建议始终限制包含的数量,因为它们不仅会增加查询的大小和复杂性(正如您所注意到的那样),而且还会增加结果集的长度和宽度。此外,它们经常被转换为外连接。
除此之外,您使用Contains的方式是正确的。
很抱歉,在不了解您的数据模型和涉及表的大小的情况下,很难提供更具体的建议。

2
EF性能方面的好文章 http://msdn.microsoft.com/zh-cn/data/hh949853.aspx - Pavel Voronin
1
很棒的文章!与我们问题相关的重要引用:“一旦您在查询中包含三个或更多实体,请考虑切换到延迟加载。”和“具有多个Include语句的查询需要相对较长的时间才能通过我们的内部计划编译器。”以及“这样的查询将在单个有效负载中从数据库中带入大型连接图,这将加剧任何带宽问题”。 - Gert Arnold

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接