3

Wee 从数据库加载大对象图。查询有很多 Includes,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;
        }
4

1 回答 1

2

几乎可以肯定的是,尽管有更多的 db 往返,但将查询分成几部分效果更好。总是建议限制包含的数量,因为它们不仅会放大查询的大小和复杂性(正如您所注意到的),而且还会在长度和宽度上放大结果集。此外,它们经常被翻译成外部连接。

除此之外,使用Contains您的方式是可以的。

抱歉,如果不知道您的数据模型和所涉及的表的大小,很难更具体。

于 2012-11-02T20:56:25.480 回答