我在oracle 10中运行查询 select A from B where C = D
B有数百万条记录,C上没有索引
第一次运行它需要大约30秒,第二次运行查询需要大约1秒钟。
显然它正在缓存一些东西,我希望它能够阻止它,每次我运行查询时我都希望它需要30秒 - 就像它第一次运行一样。
- 为了使问题可读,我过度简化了我所遇到的问题。
谢谢
我在oracle 10中运行查询 select A from B where C = D
B有数百万条记录,C上没有索引
第一次运行它需要大约30秒,第二次运行查询需要大约1秒钟。
显然它正在缓存一些东西,我希望它能够阻止它,每次我运行查询时我都希望它需要30秒 - 就像它第一次运行一样。
谢谢
清除缓存以测量性能是可能的,但非常笨拙。
跟踪调优工作性能的一个非常好的衡量标准是计算查询执行期间读取块的数量。最简单的方法之一是使用带有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 |
---------------------------------------------------------------------------------------------------------------------
看到这个 题...
它展示了如何清除数据和执行计划的缓存,但也扩展了它是否是一个好主意。
显而易见的答案是每个测试用例多次运行查询,并抛出第一个结果。
由于涉及各种缓存,因此完全复制第一次查询运行的条件并不容易:有些是Oracle缓存(游标,缓冲区等);一些是OS(磁盘缓存,取决于Oracle配置);一些是硬件(SAN,RAID,磁盘)。
在每次试用之前重新启动数据库服务器可能会非常接近一致的条件。