我遇到了一些对我来说似乎很奇怪的行为。我在 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 或其他地方吗?还有其他提示吗?
提前致谢!
答案1
这是典型的日志提前写行为。当数据库中的页面更新时,更新首先写入日志,然后应用于内存页面。页面在内存中保持脏状态,直到检查点发生,此时将其写入磁盘。必须在更新之前写入日志以支持恢复和回滚。除非发生这两种情况之一(恢复或回滚),否则无需再次读取日志。因此,您看到的行为对于修改 tempdb 中的页面的系统来说是典型的。只有在发生回滚时才会看到日志读取(因为 tempdb 无法进行恢复)。
一个更有趣的问题是,为什么 tempdb 中会发生如此多的页面更新?典型的罪魁祸首要么是直接更新(例如,使用 ASP 的 tempdb 中的会话状态),要么是间接更新(查询计划中的假脱机和排序)。