问题背景:我想为我的网站实现一个缓存系统。目前我们正在探索使用 memcache 来实现这一点。但是,我想看看 SQL Server 中是否存在类似的东西。我知道 MySQL 有查询缓存,虽然它不是分布式的,但它是一种“权宜之计”。MySQL 查询缓存是否等同于 SQL Server 中的缓冲区缓存?
我的问题是:
- 有没有办法知道当前存储在缓冲区缓存中的内容?
- 接下来,有没有办法强制将某些表或结果集放入缓存中?我对缓冲区和过程缓存中发生的事情有多少控制权?我知道以前有一个 DBCC PINTABLE 命令,但后来已经停用了。
- 稍微偏离主题:缓存是否应该存在于数据库层?或者使用 Velocity/Memcache 管理缓存更为谨慎?是吗?为什么?在处理具有重叠触发器的许多对象时,缓存失效似乎有点麻烦。
谢谢!
答案1
1)是的,您可以看到 Sql Server 缓冲区缓存 (2005 和 2008) 中的内容 --- 演示:按对象和 index.sql 计算缓冲区数量 --- 按对象计算内存数量。 --- 按对象(表、索引)细分缓冲区 SELECT b.database_id, database_name = CASE b.database_id WHEN 32767 THEN 'Resource' ELSE db_name(b.database_id) END, p.object_id, Object_Name = object_name(p.object_id, database_id), p.index_id, buffer_count=count(*) FROM sys.allocation_units a JOIN sys.dm_os_buffer_descriptors b ON a.allocation_unit_id = b.allocation_unit_id JOIN sys.partitions p ON a.container_id = p.hobt_id WHERE object_id > 99 GROUP BY b.database_id, p.object_id, p.index_id ORDER BY buffer_count DESC
2) 您可以在 2005 年将表固定在缓存中 - 此功能在 2008 年被弃用...我认为 SQL Server 用于将热表保留在缓存中的算法比您决定将表固定在缓存中更好。时间最好花在查询调整上。
3)这取决于......
答案2
我认为你的第三点完全没有偏离主题。如果你希望为你的网站实现缓存,我认为在 Web 层使用 memcache 或类似的东西是有意义的。
实施缓存的原因之一是首先要减少对数据库的调用次数。如果将缓存放在数据库中,则不会节省太多。
您的性能还很大程度上取决于您的对象模型以及您查询数据库的方式。如果您缓存对象及其全部或大部分属性,那么您将获得比为每个页面缓存特定结果集更好的缓存性能,因为使用特定对象的每个页面都可以使用相同的缓存记录。
无论您选择哪种方法,数据库都会有自己的内部缓存。当您的 Web 缓存要求您访问数据库时,这将有助于提高您的查询性能,而不必为每个数据页面访问磁盘。
答案3
抱歉,这个问题已经过去了大约一年,但我刚刚才遇到。
回应 Joe E O 的第二个回答,“...您可以在 2005 年将表固定在缓存中...”固定表在 SQL2005 中不再起作用...而罪魁祸首是:
http://www.sqlskills.com/BLOGS/PAUL/post/DBCC-PINTABLE.aspx
并且我相信,现在已经从 SQL2008 中完全删除了。
高血压
谦卑的DBA
答案4
查询缓存与缓冲区缓存的不同之处在于,缓冲区缓存包含实际数据块,而查询缓存包含特定查询的结果。换句话说,查询缓存仅在查询与之前运行的查询相同或几乎相同时才有效,通常仅限于同一用户。
只要查询访问任何其他查询最近访问过的数据,缓冲区缓存就会生效。
恐怕我不知道有没有一种简单的方法可以查看缓冲池中当前的数据,也不知道有没有一种支持将对象固定到 SQL Server 2005 中的缓存的方法。我想补充一点,我主要是 Oracle DBA,所以有机会让对 MS-SQL 有更多了解的人对此有所启发。
不管应用程序级缓存如何,数据库层的缓冲区缓存对于应用程序性能来说都是必不可少的。系统文件缓存和数据库缓冲区缓存之间可能存在一些重叠,在某些情况下,让 RDBMS 绕过系统缓存可能会有好处。