【问题标题】:Oracle 11g - query appears to cache even with NOCACHE hintOracle 11g - 即使有 NOCACHE 提示,查询似乎也会缓存
【发布时间】:2016-01-31 11:55:49
【问题描述】:

我正在使用 cx_Oracle 模块在 Python 中进行一些数据库基准测试。为了对结果进行基准测试,我运行了 150 个唯一查询并为每个查询的执行计时。我正在运行这样的东西:

c = connection.cursor()
starttime = time.time()
c.execute('SELECT /*+ NOCACHE */ COUNT (*) AS ROWCOUNT FROM (' + sql + ')')
endtime = time.time()
runtime = endtime - starttime

每个查询都是通过变量sql 传入的,它们在长度、运行时间和它们访问的表方面有很大差异。话虽如此,所有查询都表现出以下行为:

第一次运行:非常慢(相对)

第 2 次运行: 明显更快(需要 1/2 到 1/5 的时间)

第三次运行:略快于第二次运行

所有后续运行 >= 4: 大约等于第 3 次运行

我需要禁用缓存才能获得准确的结果,但前几次运行确实会丢失我的数据;好像NOCACHE 根本不工作……这是怎么回事?

编辑:Allan 回答了我的问题,但对于任何可能感兴趣的人,我做了更多的研究,发现这两个页面也很有帮助:

How to clear all cached items in Oracle

http://www.dba-oracle.com/t_flush_buffer_cache.htm

【问题讨论】:

  • 希望实时系统进行缓存,因为这样可以提高性能。所以你不应该安排你的基准测试,以便丢弃每个查询的前两次运行(a.k.a.“老化”)。您在sql 有哪些疑问?您当前传入查询的方式不允许使用绑定变量,即如果查询包含输入参数,这些将嵌入到查询文字中,这将导致hard parse在每次执行之前,我认为这会导致 #1 中的滞后。
  • 我有点困惑。由于我假设查询将在生产中被硬解析,因此我想要保持较慢的运行。事实上,我实际上是想让它们与第一次运行保持一致。这种情况需要不缓存的查询,因为测试是在具有不同配置的多个数据库中进行的,并且系统上的用户只会运行一次查询,这使得缓存时间对于基准测试无效。
  • 好吧,我不知道您正在测试在生产环境中只会运行一次的查询。如果查询真的很繁重,那么硬解析可能不是这里最大的因素,而是查询执行速度很慢。您可以使用像 tkprof 这样的 Oracle 实用程序进行分析吗?
  • 我可能会在星期一调查一下。我不是 DBA,我只是为他编写基准脚本的人。我对这些东西还很陌生,所以我还有很多东西要学!
  • @McGlothlin 需要注意的是,Oracle 不会缓存查询结果,它会缓存最常用的表和索引块。这意味着不同的查询可以利用相同的缓存。您很可能确实希望在任何 OLTP 测试中排除“老化”时间。通常alter system flush buffer_cache; 只会帮助在数据仓库中进行实际测试。不幸的是,这使您的测试变得更加困难 - 如果没有完美匹配的查询、数据和环境,就很难复制缓存行为。

标签: python oracle oracle11g cx-oracle


【解决方案1】:

来自documentation

NOCACHE 提示指定为表检索的块是 放置在缓冲区中 LRU 列表最近最少使用的一端 执行全表扫描时缓存。这是正常行为 缓冲区缓存中的块数。

由此看来,nocache 提示根本没有达到您的预期。

您可以通过运行ALTER SYSTEM FLUSH SHARED_POOL 来清除共享缓存,通过运行ALTER SYSTEM FLUSH BUFFER_CACHE 来清除缓冲区缓存。您需要在每次查询之间执行此操作,以防止缓存被使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-02
    • 2020-09-10
    • 2018-12-20
    • 1970-01-01
    相关资源
    最近更新 更多