RAM是新磁盘–以及如何衡量其性能(2015)

2021-01-22 03:51:05

如果您尚未阅读本系列的前几部分,请参见以下链接:[第1部分|第2部分 ]。

在本系列的第一部分中,我说过RAM访问是现代内存数据库引擎的慢速组件,为了提高性能,您希望尽可能减少RAM访问。新的列式数据格式减少了内存流量,这是实现出色的内存处理性能的最重要的推动力,而SIMD只是锦上添花。

在第二部分中,我还展示了如何使用Linux perf stat命令来测量(Oracle)进程的CPU效率。您的应用程序实际使用CPU执行单元的程度取决于许多因素。最大的因素是您的进程的缓存效率取决于CPU缓存大小和应用程序的内存访问模式。无论top或vmstat之类的OS CPU记帐工具如何显示,您的``100%繁忙''CPU可能实际上会在内部空闲时花费大量时间,并且管道停滞不前,等待某些事件(例如内存行到达)从RAM)发生。

幸运的是,由于现代处理器内置了CPU性能计数器(CPC),因此有许多工具可以测量CPU内部实际发生的情况。

理解CPU效率的一个重要指标是IPC(每个周期的指令)。几年前,人们实际上在谈论反指标CPI(每条指令的周期),因为完成一条指令的执行平均要花费一个以上的CPU周期(同样由于上述原因,例如内存停顿)。但是,由于当今的超标量处理器在现代CPU的多个执行单元上无序执行-并且具有大的CPU缓存-一个经过优化的应用程序可以在单个CPU周期内执行多个指令,因此使用IPC(每周期指令数)指标。使用IPC,越高越好。

这是上一篇文章的摘要,该过程正在对Oracle表进行完全缓存的全表扫描(以普通的面向行格式存储):

进程ID' 34783'的性能计数器统计信息:27373.819908任务时钟#0.912 CPU使用了86,428,653,040周期#3.157 GHz [33.33%] 32,115,412,877指令#0.37 insns每个周期#2.39每个insn停止的周期[40.00%] 76,697,049,420失速的循环前端#88.74%的前端循环空闲[40.00%] 58,627,393,395失速的循环后端#67.83%的后端循环空闲[40.00%] 256,440,384高速缓存引用#9.368 M / sec [26.67%] 222,036,981高速缓存丢失#86.584所有缓存参考的百分比[26.66%] 30.000601214秒已过去的时间

上述任务的IPC非常糟糕– CPU每个CPU周期只能完成0.37条指令。平均而言,每条指令执行在执行管道中停顿了2.39个CPU周期。

注意:可以使用各种其他指标来深入研究为什么CPU花费这么多时间停滞(例如高速缓存未命中和RAM访问)。我在本系列的第2部分中介绍了典型的性能统计指标,因此这里不再赘述。

我实验的目的是在不同的数据存储格式上测量Oracle中不同数据扫描方法的CPU效率数量。我只关注数据扫描和过滤,而不关注联接或聚合。我确保所有测试运行都将所有内容缓存在Oracle的缓冲区缓存或内存中的列存储中-因此磁盘IO并不是此处考虑的因素(同样,请在本系列的第2部分中详细了解我的测试环境设置)。

尽管我正在测试全表扫描速度,但我还添加了两个通过索引范围扫描来扫描整个表行的示例。这使我能够显示访问表的大部分行时索引范围扫描的效率如何,即使所有行都缓存在内存中也是如此。即使您在某些测试中看到了不同的WHERE子句,它们的设计也都使其遍历表的所有行(只是使用不同的访问模式和代码路径)。

请注意,除了最后一个实验以外,所有实验都是如何在启用了不同选项(例如索引扫描或内存中访问路径)的情况下扫描同一物理表的。上一个实验针对的是同一张表的副本(相同的列,相同的行),但只是以HCC格式进行了物理格式化(并完全缓存在缓冲区缓存中)。

仅查看不同实验的CPU性能计数器是不够的,它们太低了。从整体上看,我们还想知道应用程序正在执行多少工作(例如逻辑IO等)以及在每种情况下最终要处理多少行。我还验证了我是否确实获得了所需的确切执行计划,访问路径,并且使用常规Oracle指标没有发生物理IO或其他等待事件(请参见下面的日志)。

这是带有SQL监控报告,快照程序和性能统计信息的完整性能编号的实验日志文件:

我还将所有这些数字(加上一些衍生值)放入电子表格中。 为了方便起见,我粘贴了以下数据的屏幕截图,但是您可以在此处访问带有原始数据和图表的整个电子表格(请注意,电子表格中具有多个选项卡和可配置的数据透视图): 让我们从简单的事情开始,逐步深入研究。 我将从列出task-clock-ms指标开始,该指标显示每次测试表扫描中Oracle进程的CPU时间使用情况(以毫秒为单位)。 此指标来自操作系统级别,而不来自CPU内部: