【问题标题】:Using Linq-to-SQL preload without joins使用没有连接的 Linq-to-SQL 预加载
【发布时间】:2011-03-14 17:35:09
【问题描述】:

像许多人一样,我试图从我的应用中获得最佳性能,同时尽可能保持代码的简单和可读性。我正在使用 Linq-to-SQL,并且我真的试图让我的数据层尽可能地具有声明性。

我假设 SQL 调用是最昂贵的操作。因此,我尽量减少它们的数量,但尽量避免难以优化的疯狂复杂查询。

举个例子:我在我的 DataContext 中使用DataLoadOptions——它的目标是通过预加载相关实体来最小化查询的数量。 (也就是急切加载与延迟加载。)

问题:Linq 使用连接来实现目标。与所有事情一样,这是一种权衡。我得到的查询越来越少,但那些加入的查询更加复杂和昂贵。进入 SQL Profiler 可以清楚地说明这一点。

所以,我想在 Linq 中提供一个选项来在没有连接的情况下预加载。这可能吗?下面是它的样子:

我有一个Persons 表、一个Items 表和一个PersonItems 表来提供多对多关系。在加载 Persons 集合时,我希望他们的所有 PersonItems 和 Items 也都急切地加载。

Linq 当前使用一个包含两个连接的大型查询来执行此操作。我宁愿它做的是三个非连接查询:一个用于 Persons,一个用于与这些 Persons 相关的所有 PersonItems,一个用于与这些 PersonItems 相关的所有 Items。然后 Linq 会自动将它们排列到相关实体中。

其中的每一个都是快速的、firehose 类型的查询。从长远来看,它可以实现可预测的网络规模性能。

见过吗?

【问题讨论】:

  • 对于答案来说还不够好,但我想我只是想知道为什么你似乎对加入有一种自动的负面反应,而没有分析它们是否真的在性能上更差。另一方面,有人可能会指出,在一个连接时执行多个查询——使用适当的外键——可以做得同样好,或者更好。最后,代码也可能会变得更简单。
  • 很公平,尽管我将复杂性视为性能的代表。它目前表现良好,但似乎连接在费用方面必须呈指数级 - 每个连接乘以行 x 行。这也是性能和规模之间的区别。规模是指性能是可预测的,即线性的。

标签: linq-to-sql eager-loading


【解决方案1】:

我相信您所描述的三个非连接查询在哪里完成基本上是在执行单个连接查询时发生的事情。我可能是错的,但如果是这种情况,单个查询将更有效,因为只涉及一个数据库查询而不是三个。如果您遇到性能问题,我会确保您加入的列已编入索引(您应该在 SQL 分析器中看不到表扫描)。如果这还不够,您可以编写一个自定义存储过程来获取您需要的数据(假设您不需要每个对象的每一列,这将允许您使用比索引扫描更快的索引查找),或者你也可以去规范化(在你的表中复制数据),这样就不会发生连接。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多