问题 我的查询第二次运行得更快,我该怎么做呢?


我在oracle 10中运行查询 select A from B where C = D B有数百万条记录,C上没有索引

第一次运行它需要大约30秒,第二次运行查询需要大约1秒钟。

显然它正在缓存一些东西,我希望它能够阻止它,每次我运行查询时我都希望它需要30秒 - 就像它第一次运行一样。

  • 为了使问题可读,我过度简化了我所遇到的问题。

谢谢


7954
2017-07-07 14:13


起源

你介意解释为什么你希望它继续慢慢运行吗? - Aducci
可能的答案:性能调整和测试 - MatBailie
如何强制进行硬解析: oracle-randolf.blogspot.com/2009/02/... - OMG Ponies
我需要一种一致的测试方法,如果我创建的索引做得很好,如果我的查询不需要同时运行同一组数据,那么很难对它进行科学研究。 - LoudNPossiblyWrong


答案:


清除缓存以测量性能是可能的,但非常笨拙。

跟踪调优工作性能的一个非常好的衡量标准是计算查询执行期间读取块的数量。最简单的方法之一是使用带有autotrace的sqlplus,如下所示:

set autotrace traceonly
<your query>

输出

...
Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          1  consistent gets
          0  physical reads
          0  redo size
        363  bytes sent via SQL*Net to client
        364  bytes received via SQL*Net from client
          4  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

从缓存或磁盘读取的块数是 consistent gets

另一种方法是使用增加的统计信息运行查询,即使用提示 gather_plan_statistics 然后从游标缓存查看查询计划:

auto autotrace off
set serveroutput off
<your query with hint gather_plan_statistics>
select * from table(dbms_xplan.display_cursor(null,null,'typical allstats'));

读取的块数按列输出 buffers

---------------------------------------------------------------------------------------------------------------------
| Id  | Operation        | Name           | Starts | E-Rows | Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
---------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |                |      3 |        |     1 (100)|          |      3 |00:00:00.01 |       3 |
|   1 |  SORT AGGREGATE  |                |      3 |      1 |            |          |      3 |00:00:00.01 |       3 |
|   2 |   INDEX FULL SCAN| ABCDEF         |      3 |    176 |     1   (0)| 00:00:01 |    528 |00:00:00.01 |       3 |
---------------------------------------------------------------------------------------------------------------------

9
2017-07-07 14:48



有趣但我在分析函数中使用的列上创建了一个复合索引,我想看看这个索引是否有效以及如何有效。我能用你描述的效果吗?谢谢 - LoudNPossiblyWrong
是的,查询计划的每个部分都会显示其相关成本。如果没有意外发生,那将包括您的复合索引。意想不到的事情可能是您的索引未被使用。 - Peter G.


看到这个 ...

它展示了如何清除数据和执行计划的缓存,但也扩展了它是否是一个好主意。


5
2017-07-07 14:16





显而易见的答案是每个测试用例多次运行查询,并抛出第一个结果。

由于涉及各种缓存,因此完全复制第一次查询运行的条件并不容易:有些是Oracle缓存(游标,缓冲区等);一些是OS(磁盘缓存,取决于Oracle配置);一些是硬件(SAN,RAID,磁盘)。

在每次试用之前重新启动数据库服务器可能会非常接近一致的条件。


2
2017-07-07 14:45



第一个结果不是最准确吗? - EvilTeach
实际上,第一个结果不是最准确吗?如果你运行了100次,第一次运行30次,其余运行时间为1s,我认为 - 就用户体验而言 - 30s值非常不准确。 - Philip Kelley


它可能对你有所帮助

http://www.mssqltips.com/tip.asp?tip=1360

CHECKPOINT;
GO DBCC DROPCLEANBUFFERS;


-2
2017-07-07 14:36



另一个方案 - Irvin Dua
EXEC sys.sp_configure N'max服务器内存(MB)',N'2147483646'TO RECONFIGURE WITH OVERRIDE GO(尺寸由你决定) - Irvin Dua
错误的数据库......对Oracle来说太过分了。 (看看问题上的标签) - derobert
阅读问题,这是关于oracle,而不是sql server。 - LoudNPossiblyWrong