我遇到了一些对我来说很奇怪的行为。我在 Windows 7 上使用 SQL Server 2008 Enterprise,32 位(四核 2)(用于测试)。
我有一个使用两个表变量的存储过程。一个插入大约 2 或 3 行,另一个插入 0 到 100 行。然后我从第二个中选择大概 20-60 行,仅此而已。
性能相当快。我创建了一个简单的应用程序来循环执行查询,我可以使用 1 个线程执行 1300/秒,使用 4 个线程执行大约 4000 个。
输入 tempdb:当我打开资源监视器查看发生了什么时,我看到有大量写入 tempdb 日志文件。(我在 2 个不同的物理磁盘上创建了 2、100MB - 它们似乎没有超过 100MB。)读取活动为零- 整个数据库都适合 RAM。
在单线程运行查询的情况下,对 tempdb 日志文件的写入速度约为 3MB/秒。随着我的增加,每个日志文件的速度会上升到 20MB/秒。
在 SQL 活动监视器中,当我使用 5 个线程时,“等待时间”的“日志记录”超过 300 毫秒/秒。在 3 个线程时,它降至 25 毫秒/秒。
问题:发生了什么事?为什么 SQL 会疯狂地写入 tempdb 日志,但发出零读取(我在资源监视器或活动监视器中看不到读取活动)?在非测试环境中,在我看来,额外的 40MB/秒写入可能会损害整体性能。
我知道表变量(@foo)并不总是存储在内存中,但我很困惑为什么 tempdb 必须记录所有这些东西。我该如何解决它在做什么?我可以将 tempdb 的日志放在 ramdisk 上吗?还有其他指针吗?
提前致谢!
这是典型的日志预写行为。当数据库中的页面更新时,更新首先写入日志,然后应用于内存页面。该页面在内存中保持脏状态,直到发生检查点,此时它被写入磁盘。必须在更新之前写入日志以支持恢复和回滚。除非发生这两种情况之一(恢复或回滚),否则无需再次读取日志。因此,您看到的行为对于修改 tempdb 中的页面的系统来说是典型的。如果发生回滚,您只会看到日志读取(因为 tempdb 无法进行恢复)。
一个更有趣的问题是,为什么 tempdb 中会发生如此多的页面更新?典型的罪魁祸首是直接更新(例如,带有 ASP 的 tempdb 中的会话状态)或间接更新(查询计划中的假脱机和排序)。