我正在使用 Oracle 10G 和 Oracle SQL developer ver 3。我想知道 Oracle 是否在某处存储/缓存查询的结果,以便接下来您使用相同的参数执行相同的查询,检索数据所需的时间更短比你第一次执行脚本。
如果它会缓存这些结果多长时间?
我试图执行一个选择 SQL 脚本,在重复 3 次后,它检索数据和显示所需的时间减少了近一半。但有时,如果我在另一个数据库上执行相同的脚本,即使我重复多次,它似乎也不会做出任何改变。
2 回答
Oracle 在库缓存中缓存 SQL 语句。当您多次执行一条语句时(无论是否使用相同的绑定变量值),Oracle 都会使用库缓存中的数据来避免重新解析 SQL 语句并生成新的查询计划。但是,当您考虑调整单个查询时,这种缓存不太可能对性能产生有意义的影响。解析 SQL 语句并生成查询计划通常是一个非常快速的过程。
Oracle 还在缓冲区缓存中缓存数据块。因此,当您执行查询并读取特定数据块以获取表中特定行的数据时,该块将被缓存。这经常允许使用相同的绑定变量集执行相同的 SQL 语句来执行更少的物理读取,因为查询需要读取的更多块被缓存。通常,这些块存储在 LRU(最近最少使用)缓存中,因此它们将被缓存直到它过期,因为其他块更受欢迎(有例外情况使缓冲区缓存不同于纯 LRU 缓存 - 块例如,通过全表扫描读取的数据通常放在缓存的末尾而不是开头 - 但通常将其视为 LRU 缓存是合理的)。
然后你就拥有了 Oracle 之外的所有缓存。例如,您的操作系统通常会配置为缓存读取的文件部分,因此即使一个块在 Oracle 的缓冲区缓存中老化,它也可能在文件系统缓存中,这仍然比从磁盘读取块快得多. 大多数 SAN 还将缓存最近使用的数据,这将允许检索该数据而无需从磁盘读取它。通常,如果数据缓存在 Oracle 中会更有效,但从文件系统缓存或 SAN 缓存中检索块仍然比从物理驱动器读取块更有效。
连续多次运行查询通常会变得更快,因为您会强制将更多您感兴趣的块缓存在某个地方,并大大减少系统需要执行的物理 I/O 量。当然,如果您的查询不受 I/O 限制,或者您的查询针对的是已经缓存的数据,则差异会小得多。但是,完全有可能同一查询会从一天运行多次而不是第二天完全受益,因为有一天它感兴趣的块都没有被缓存和其他会话,另一天所有的它感兴趣的块已经被缓存了。
在 11g 中,您可以选择配置结果缓存,它允许您缓存特定查询的结果,而不仅仅是为了生成这些结果而读取的块。
Oracle 通常会缓存它从磁盘读取的每个页面,并会尝试尽可能长时间地保存该信息(它基本上是一个 MRU 缓存)。在尝试衡量数据库操作的性能时,这是一个非常重要的考虑因素;查询的后续执行通常会比第一次快得多。
如果查询需要很少的 I/O,或者超出缓存的容量,或者缓存被其他用户大量使用,则缓存可能不明显。
请注意,查询计划也会被缓存,这也会影响观察到的查询性能。