我一直在对用于替换现有生产服务器的新(虚拟)服务器进行一些测试。我们怀疑当前的生产服务器规格过高,因此正在从低级别调整新服务器的虚拟组件(RAM、CPU 等),直到性能适合处理当前工作负载。
虽然认识到新服务器处理现有服务器工作负载能力的真正测试是针对新服务器测试该工作负载,但出于兴趣,我对现有服务器和新服务器进行了一些简单、随意的测试:
- 恢复数据库 - 读取速度
- 备份数据库 - 写入速度
- 大型数据库上的 DBCC CHECKDB - 耗时
(为了使上述所有测试保持一致,两台服务器上都使用了相同的数据库备份)
以上所有都支持新服务器(更快的读写,更快的 CHECKDB)
我做的最后一个基本测试是测试在SELECT *
冷缓存和热缓存上的最大表之一上执行简单操作所需的时间,以进一步了解读取速度。
下面是我在两台服务器上运行的测试代码
USE StackOverflow
SET STATISTICS IO, TIME ON
CHECKPOINT
DBCC DROPCLEANBUFFERS
SELECT * FROM Users /* cold cache run */
SELECT * FROM Users /* warm cache run */
统计IO如下:
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 12 ms.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
SQL Server Execution Times:
CPU time = 62 ms, elapsed time = 266 ms.
(14080580 rows affected)
Table 'Users'. Scan count 1, logical reads 250190, physical reads 1, page server reads 0, read-ahead reads 250200, page server read-ahead reads 0, lob logical reads 1387, lob physical reads 58, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
SQL Server Execution Times:
CPU time = 24047 ms, elapsed time = 508456 ms.
(14080580 rows affected)
Table 'Users'. Scan count 1, logical reads 250190, physical reads 0, page server reads 0, read-ahead reads 0, page server read-ahead reads 0, lob logical reads 1385, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
SQL Server Execution Times:
CPU time = 23297 ms, elapsed time = 478627 ms.
我的两台服务器上的结果都相似,但令我印象深刻的是,从磁盘而不是 RAM 读取时,经过的时间只慢了 30 秒。
我对 SQL Server 为何将所有内容读入缓冲池的理解是 RAM 比磁盘快——在这个测试中,RAM 只快 6%。
基于上述,如果我的“现实生活”查询是 2000 毫秒从缓存中读取,那么从 RAM 读取数据需要 3200 毫秒。可以说,这不是一个明显的区别。
那么,为什么我们要竭尽全力确保数据和服务器有尽可能多的 RAM 来缓存数据,而它似乎只快 6% 呢?
我的问题是故意的,因为我觉得我在这里忽略了一些东西,我很欣赏我的测试本质上非常简单。
对我忽略的事情的想法:
- 如果数据在 RAM 中,则可以减少繁忙服务器上的磁盘争用
- 我很欣赏 RAM 用于 SQL Server 中的其他东西,而不仅仅是缓冲池
- SQL Server 大概在早期磁盘比现代 SSD 慢得多的时候就有这种架构
您为测量冷缓存和热缓存的差异而运行的测试查询将花费大部分执行时间等待ASYNC_NETWORK_IO。在您的情况下,将 1400 万行发送到 SSMS 可能需要大约 450 秒。如果减去等待时间,您可能会发现冷缓存查询所需的时间大约是暖缓存查询的两倍。
SQL Server 也有各种减少 I/O 等待时间的技巧。其中一个技巧是预读读取。您运行的查询类型可能会从预读中受益不少。几乎所有的 I/O 都是通过预读机制完成的:
并非所有查询都能从预读中获得如此大的优势。我碰巧写了一篇最近的博客文章,其中有一个由于 I/O 等待而导致查询性能非常差的示例。复制相关部分:
回到你的系统,你可以考虑
COUNT_BIG(*)
对桌子发出一个。这会将客户端等待时间减少到几乎为零,并将更直接地向您展示冷缓存和热缓存之间的区别。如果你想在新服务器上测试 I/O 而没有预读的好处,你可以尝试运行这篇博文中提到的演示代码:除了乔的帖子:
备份和恢复不使用缓冲池 (BP)。Checkdb 可能读取了太多数据,因此缓存重用的可能性不高。
至于您的 SELECT:与缓存中的数据相比,它读取了多少数据?
此外,您在此 SQL Server 上的负载模式是什么?
如果要在读取实际数据量的地方进行加载,并有机会进行缓存重用,您可能想要做什么。您可以使用最大服务器内存,上下调整以调整您可以在 BP 中拥有的数据量,并在此基础上看到差异。在两台服务器上运行此程序,最大服务器内存相对较高和较低。
以上将花费比你已经做的更多的时间。可能要一两天来创建工作量。所以最后,归结为你是否觉得那段时间值得。
如果您想要一个负载的起点,即执行索引搜索,其中既有宽表也有窄表,以及高选择性和低选择性的查询,那么您可以使用我为我的“碎片是否重要”博客文章系列开发的负载。您必须对其进行调整以满足您的需求,但它可能会为您节省一些时间:http ://sqlblog.karaszi.com/fragmentation-the-final-installment/
对于本身具有大缓冲池的 OLAP 工作负载,可能无法提高性能。不管你怎么看,一张 1TB 的桌子永远都装不下 200GB 的 RAM。因此,每次扫描时都必须从磁盘中提取此类表的某些部分。但是拥有所有这些 RAM 仍然很有用。随着大表的出现,大的散列连接探针构建、大的排序、用于窗口函数的大工作空间以及其他一切。留在内存中并且不会溢出到磁盘的那些越多,整个工作负载完成的速度就越快。
您对架构根源的观察也是有效的。回到过去,不仅一切都慢了很多,而且也少了很多。数据保存在磁盘上。它被带入内存进行处理,并保留一小段时间以防它被证明有用。大多数情况下,磁盘是数据所在的地方。如今,一个受人尊敬的 OLTP 服务器具有与 DB 大小相当的内存。数据存在于内存中。磁盘仅用于备份,以防电源故障。旧架构不能很好地服务于新硬件。Michael Stonebreaker 有很多关于这个主题的有理有据的文章。