2

让我从描述场景开始。我有一个带有 SQL Server 2008 的 MVC 3 应用程序。在其中一个页面中,我们显示了从数据库返回的产品列表,并且每个登录用户都是唯一的。用于返回产品列表的 SQL 查询(实际上是 VIEW)非常昂贵。

  • 它基于非常复杂的业务需求,现阶段无法更改。
  • 数据库架构无法更改或重新设计,因为它被其他应用程序使用。
  • 有 50k 个产品和 5k 个用户(每个用户可以访问 1 到 50k 个产品)。

为了显示登录用户的产品页面,我们使用:

SELECT TOP X * FROM [VIEW] WHERE UserID = @UserId -- where 'X' is the size of the page

上面的查询最多返回 50 行(最大页面大小)。WHERE 子句将行数限制为最多 50k(用户有权访问的产品)。加载页面大约需要 5 到 7 秒,而这正是上面的 SQL 查询在 SQL 中运行所需的时间。 问题

用户进入产品页面,很可能使用分页,重新排序结果,进入详细信息页面等,然后返回列表。并且每次显示结果需要5-7s。

这是不可接受的,但同时业务团队已经接受第一次加载产品页面可能需要 5-7 秒。因此,我们想到了CACHING

我们现在有两个选项可供选择,至少对我而言,最“明显”的一个是使用 .Net 缓存(在内存中/在 proc 中)。(请注意,由于我们的提供商/托管合作伙伴的技术限制,目前不允许分布式缓存)。

但我对此不太满意。我们最终可能会在内存中有很多产品(当有 50 或 100 个用户同时登录时),这可能会导致服务器上的其他问题,例如 .Net 在我们的代码插入新项目时不断删除缓存项目以释放​​空间。

第二选项:

这里的主要问题是生成用户 x 产品 x 访问视图非常昂贵,因此我们认为我们可以创建一个平面表(或者换句话说,数据库中所有产品 x 用户的缓存)。该表将完全是视图的结果。但是,如果添加新产品、更改用户权限等,结果可能随时更改。因此我们需要不断刷新表(这可能需要几秒钟),这开始变得有点复杂。

同样,尽管我们可以实现某种缓存提供程序,并且根据用户的请求,我们将运行原始 SQL 查询并从视图中选择产品(5-7 秒,只接受一次)并将结果保存在平面中SQL 中名为 ProductUserAccessCache 的表。下一个请求,我们将通过快速查询从这个缓存表中获取值(因为我们可以很容易地识别为该特定用户缓存的结果),而无需在 SQL 中进行计算。每当添加产品或更改权限时,我们都会截断缓存表,并在新请求时为请求的用户重新填充该表。这对我来说似乎并不太复杂,但我们在这里所做的基本上是创建一个新的缓存“提供程序”。

  • 有没有人有这种问题的经验?
  • 使用 .Net 缓存(在 proc 中)会更好吗?
  • 有什么建议么?
4

1 回答 1

1

前段时间我们遇到了类似的问题,我们正在考虑使用 EF 缓存来避免检索信息的延迟。我们的问题是 1 - 2 秒。延迟。以下是一些可能有助于如何缓存扩展 EF 的表的信息。缓存的缺点之一是您需要的信息有多新鲜,因此您需要相应地设置缓存过期时间。根据该到期时间,用户可能需要等待比他们想要的更多时间来获取新信息,但如果您的用户可以接受他们可能会看到过时的信息以避免延迟,那么权衡是值得的。

在我们的场景中,我们决定更好地获得新鲜信息而不是快速,但正如我之前所说,我们的等待时间并没有那么长。

希望能帮助到你

于 2013-04-08T14:47:32.010 回答