2

问题背景:我正在为我的网站实施缓存系统。目前我们正在探索 memcache 作为一种方法。但是,我想看看 SQL Server 是否存在类似的东西。我知道 MySQL 有查询缓存,虽然它不是分布式的,但它可以作为一种“权宜之计”措施。MySQL 查询缓存是否等同于 SQL Server 中的缓冲区缓存?

所以这是我的问题:

  1. 有没有办法知道当前存储在缓冲区缓存中?
  2. 跟进这个,有没有办法强制某些表或结果集进入缓存
  3. 我对缓冲区和过程缓存中发生的事情有多少控制权?我知道曾经有一个 DBCC PINTABLE 命令,但后来已经停止了。
  4. 稍微偏离主题:缓存是否应该存在于数据库层?还是使用 Velocity/Memcache 管理缓存更谨慎?是这样,为什么?在处理具有重叠触发器的许多对象时,似乎缓存失效是一件痛苦的事情。

谢谢!

4

4 回答 4

4

SQL Server 实现缓冲池的方式与太阳下的每个数据库产品(或多或少)相同,因为System R展示了这种方式。血淋淋的细节在事务处理:概念和技术中进行了解释。此外,它还有一个由过程缓存、权限令牌缓存和许多其他缓存类使用的缓存框架。此框架在Clock Hands - what are they for中得到了最好的描述。

但这不是应用程序通常感兴趣的缓存类型。内部数据库缓存非常适合扩展场景,其中更强大的后端数据库能够通过使用这些缓存更快地响应更多查询,但现代应用程序堆栈倾向于横向扩展 Web 服务器,真正的问题是将查询的结果缓存在 Web 场使用的缓存中。理想情况下,这个缓存应该是共享和分布式的。Memcached 和 Velocity 是此类应用程序缓存基础架构的示例。到目前为止,Memcache 已经有很长的历史了,它的用途和缺点是众所周知的,关于如何使用它、部署它、管理它和监控它有重要的专业知识。

应用层缓存的最大问题,特别是分布式缓存,是缓存失效。如何检测后端数据中发生的更改并将缓存条目标记为无效,以便新请求不使用陈旧数据。

最简单的(对于简单的定义......)替代方案是应用程序的主动失效。代码知道何时更改数据库中的实体,并且在更改发生后,它会采取额外的步骤将缓存的条目标记为无效。这有几个简短的提示:

  • 很难确切地知道哪些缓存条目将失效。依赖关系可能非常复杂,事情总是不仅仅是一个简单的表/条目,还有聚合查询、连接、分区数据等。
  • 需要代码纪律来确保修改数据的所有路径也使缓存无效。
  • 不会检测到应用程序范围之外发生的数据更改。在实践中,总是会发生应用程序范围之外的更改:使用相同数据的其他应用程序、导入/导出和 ETL 作业、手动干预等。

一个更复杂的替代方案是在发生更改时由数据库本身通知的缓存。虽然没有多少技术可以支持这一点,但如果没有数据库的积极支持,它就无法工作。SQL Server 有针对此类场景的查询通知,您可以在The Mysterious Notification阅读更多相关信息。在独立应用程序中实现基于 QN 的缓存相当复杂(而且通常做得很糟糕),但在正确实现时它工作得很好。在像 Memcached 这样的共享横向扩展缓存中这样做是一项非常强大的壮举,但也是可行的。

于 2009-11-19T22:35:56.877 回答
3

奈,

您的问题的答案如下:

  1. 来自维基 - 总是正确的......?:-)。对于Microsoft的更多答案,这是他们对Buffer Cache的描述。

    缓冲区管理

    SQL Server 在 RAM 中缓冲页面以最小化磁盘 I/O。任何 8 KB 页面都可以在内存中缓冲,当前缓冲的所有页面的集合称为缓冲区缓存。SQL Server 可用的内存量决定了将在内存中缓存多少页。缓冲区高速缓存由缓冲区管理器管理。读取或写入任何页面都会将其复制到缓冲区缓存中。随后的读取或写入将重定向到内存中的副本,而不是磁盘上的版本。只有当内存缓存一段时间没有被引用时,缓冲区管理器才会更新磁盘上的页面。在将页面写回磁盘时,使用异步 I/O,其中 I/O 操作在后台线程中完成,因此其他操作不必等待 I/O 操作完成。每个页面在写入时都会连同其校验和一起写入。回读页面时,再次计算其校验和并与存储的版本匹配,以确保页面在此期间没有被损坏或篡改。

  2. 对于这个答案,请参考上面的答案:

    读取或写入任何页面都会将其复制到缓冲区缓存中。随后的读取或写入将重定向到内存中的副本,而不是磁盘上的版本。

  3. 您可以在目录视图中查询bpool_commit_targetbpool_committed列,sys.dm_os_sys_info以分别返回作为内存目标保留的页数和缓冲区缓存中当前提交的页数。

  4. 我觉得微软已经有时间为他们的产品找出缓存并且应该被信任。

我希望这些信息对您有所帮助

谢谢!

于 2009-11-11T17:25:00.077 回答
0

对于从浏览器一直到硬件的 ASP.Net 应用程序,缓存可以具有许多不同的含义,而 IIS、应用程序、数据库位于中间。

您正在谈论的缓存是数据库级缓存,这对您的应用程序几乎是透明的。此级别的缓存将包括缓冲池、语句缓存等。确保您的数据库服务器有足够的 RAM。理论上,数据库服务器应该能够将整个数据库存储加载到内存中。除非您在启动应用程序时预先获取一些预期数据并确保它在数据库缓存中,否则您在此级别上无能为力。

另一方面是内存分布式缓存系统。除了内存缓存和速度之外,您还可以查看一些商业解决方案,例如NCacheOracle Coherence。我没有任何经验可以推荐。这种级别的缓存承诺以更便宜的成本实现可扩展性。与此相比,扩展数据库层的成本很高。不过,您可能必须考虑网络带宽等方面。这种类型的缓存,特别是失效和过期可能很复杂

您可以使用 IIS 级别(在 IIS 7 中)和 ASP.Net 级别的输出缓存在 Web 服务层进行缓存。
在应用程序级别,您可以使用 ASP.Net 缓存。这是您最能控制并为您带来好处的一种。

然后在客户端 Web 代理层进行缓存,可以通过缓存控制 HTTP 标头进行控制。

最后,您拥有浏览器级别的缓存、视图状态和小数据的 cookie。

并且不要忘记像 SAN 这样的硬件也在物理磁盘访问级别缓存。

总而言之,缓存可以发生在多个级别,您可以分析和实施适合您的场景的最佳解决方案。您已经了解了数据的稳定性和波动性、预期负载等。我相信 ASP.Net 级别的缓存(特别是对象)可以为您提供最大的灵活性和控制力。

于 2009-11-20T09:46:52.607 回答
0

当涉及到“为我的网站实施缓存系统”时,您关于 SQL Server 缓冲区缓存的具体技术问题走错了路。

当然,SQL Server 会缓存数据,以便提高性能(而且做得相当好),但在 Web 前端实现缓存层的目的是完全避免与数据库通信- 因为即使您的查询完全从 SQL Server 的缓存中完成,仍然存在开销和资源争用。

您要研究的是:memcached、Velocity、ASP.NET Cache、P&P 缓存应用程序块等。

于 2009-11-20T23:52:41.027 回答