0

我目前正在使用 SqlDataReader 和存储过程在 C# 中手写 DAL。性能很重要,但它仍然应该是可维护的......

假设有一张桌子食谱

(recipeID, author, timeNeeded, yummyFactor, ...)

和一桌食材

(recipeID, name, amount, yummyContributionFactor, ...)

现在我想查询 200 种食谱及其成分。我看到以下可能性:

  • 查询所有食谱,然后查询每个食谱的成分。
    这当然会导致 maaany 查询。
  • 在一个大的加入列表中查询所有食谱及其成分。这会造成大量无用流量,因为每个配方数据都会被多次传输。
  • 查询所有食谱,然后通过将 recipeID 列表传回数据库来一次查询所有成分。或者同时发出两个查询并返回多个结果集。回到 DAL,通过他们的 recipeID 将成分与食谱相关联。
  • 异国情调的方式:光标通过所有食谱并为每个食谱返回两个单独的食谱和成分结果集。结果集有限制吗?

要获得更多种类,可以通过 DAL 中的 ID 列表或某些参数化 SQL 条件来选择配方。

你认为哪一个的性能/混乱比最好?

4

5 回答 5

2

最佳性能/混乱比为 42。

更严肃地说,使用最简单的解决方案:使用单个查询检索所有内容。在遇到性能问题之前不要进行优化。“过早的优化是万恶之源”:)

于 2010-02-07T18:16:58.883 回答
2

如果您只需要连接两个表并且“成分”不是大量数据,那么性能和可维护性的最佳平衡可能是单个连接查询。是的,您在结果中重复了一些数据,但除非您有 100,000 行并且它使数据库服务器/网络超载,否则优化还为时过早。

如果您有许多层连接,每个连接层都具有递减的基数,那么情况会有所不同。例如,在我的一个应用程序中,我有以下内容:

Event -> EventType -> EventCategory
                   -> EventPriority
                   -> EventSource   -> EventSourceType -> Vendor

当有 10 万个事件要检索、1000 个事件类型、可能有 10 个类别/优先级、50 个来源和 5 个供应商时,这样的查询会导致大量重复,这是不可接受的。所以在那种情况下,我有一个返回多个结果集的存储过程:

  • 仅具有 EventTypeID 的所有 100k 事件
  • 适用于这些事件的具有 CategoryID、PriorityID 等的 1000 个 EventType
  • 适用于上述 EventTypes 的 10 个 EventCategories 和 EventPriorities
  • 生成 10 万个事件的 50 个事件源
  • 依此类推,你明白了。

由于基数急剧下降,因此只下载此处需要的内容并在客户端使用一些字典将其拼凑起来(如果有必要的话)要快得多。在某些情况下,低基数数据甚至可能被缓存在内存中,并且根本不会从数据库中检索(除非在应用程序启动或数据更改时)。

使用这种方法的决定性因素是大量的结果和连接的基数急剧下降,换句话说就是扇形。这实际上与大多数用法相反,可能与您在这里所做的相反。如果您选择“recipes”并加入“ingredients”,您可能正在扇出,这会使这种方法变得浪费,尤其是在只有两个表要加入的情况下。

所以我只是把它放在那里,如果性能成为一个问题,这是一个可能的选择;在您设计的这一点上,在您拥有真实世界的性能数据之前,我会简单地采用使用单个连接结果集的路线。

于 2010-02-07T18:38:23.177 回答
0

一个返回 2 个数据集的存储过程:“配方标题”和“配方详细信息”?

如果我一次需要所有数据,这就是我会做的事情。如果我一次不需要它,我仍然会得到 2 个数据集,但数据更少。

我们发现在客户端中使用它比 Andomar 建议的一个大查询要容易一些,但他/她的回答仍然非常有效。

于 2010-02-07T18:31:30.197 回答
0

我会放眼大局——你真的需要检索 200 个食谱的成分吗?当你有 2,000 个时会发生什么?

例如,如果这是在网页中,我将列出 200 个食谱(如果不是因为分页而减少),当用户单击一个以查看成分时,我将从数据库中获取成分。

如果这不可行,我将有 1 个存储过程,它返回一个包含 2 个表的 DataSet。一个是食谱,第二个是配料表。

于 2010-02-07T18:49:04.570 回答
0

“我目前正在用 C# 手写一个 DAL……”作为旁注,您可能需要查看帖子:从存储过程生成数据访问层方法。 它可以为您节省大量时间。

于 2010-02-07T18:53:05.023 回答