You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Oracle TKPROF输出疑问:当前块读、执行计划starts值及解析次数

查询语句

select s.prod_id, p.prod_name, s.cust_id, c.cust_first_name 
from sh.sales s, sh.products p, sh.customers c 
where s.prod_id = p.prod_id and s.cust_id = c.cust_id and s.amount_sold > 1500

TKPROF输出

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.03       0.03          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch      542      0.32       0.72          0       3607         28        8114
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total      544      0.35       0.76          0       3607         28        8114

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: SYS
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
      8114       8114       8114  HASH JOIN (cr=3607 pr=0 pw=0 time=450527 us starts=1 cost=859 size=469504 card=8384)
      8114       8114       8114   NESTED LOOPS (cr=1643 pr=0 pw=0 time=253284 us starts=1 cost=859 size=469504 card=8384)
      8114       8114       8114    NESTED LOOPS (cr=1643 pr=0 pw=0 time=251761 us starts=1)
      8114       8114       8114     STATISTICS COLLECTOR (cr=1643 pr=0 pw=0 time=250365 us starts=1)
      8114       8114       8114      HASH JOIN (cr=1643 pr=0 pw=0 time=250044 us starts=1 cost=454 size=368896 card=8384)
        72         72         72       NESTED LOOPS (cr=8 pr=0 pw=0 time=863 us starts=1 cost=454 size=368896 card=8384)
        72         72         72        STATISTICS COLLECTOR (cr=8 pr=0 pw=0 time=790 us starts=1)
        72         72         72         TABLE ACCESS FULL PRODUCTS (cr=8 pr=0 pw=0 time=691 us starts=1 cost=3 size=2160 card=72)
          0          0          0          PARTITION RANGE ALL PARTITION: 1 28 (cr=0 pr=0 pw=0 time=0 us starts=0 cost=451 size=1624 card=116)
          0          0          0           TABLE ACCESS BY LOCAL INDEX ROWID BATCHED SALES PARTITION: 1 28 (cr=0 pr=0 pw=0 time=0 us starts=0 cost=451 size=1624 card=116)
          0          0          0            BITMAP CONVERSION TO ROWIDS (cr=0 pr=0 pw=0 time=0 us starts=0)
          0          0          0             BITMAP INDEX SINGLE VALUE SALES_PROD_BIX PARTITION: 1 28 (cr=0 pr=0 pw=0 time=0 us starts=0)(object id 101439)
      8114       8114       8114      PARTITION RANGE ALL PARTITION: 1 28 (cr=1635 pr=0 pw=0 time=248277 us starts=1 cost=451 size=117376 card=8384)
      8114       8114       8114       TABLE ACCESS FULL SALES PARTITION: 1 28 (cr=1635 pr=0 pw=0 time=208294 us starts=28 cost=451 size=117376 card=8384)
          0          0          0    INDEX UNIQUE SCAN CUSTOMERS_PK (cr=0 pr=0 pw=0 time=0 us starts=0)(object id 101249)
          0          0          0    TABLE ACCESS BY INDEX ROWID CUSTOMERS (cr=0 pr=0 pw=0 time=0 us starts=0 cost=405 size=12 card=1)
     55500      55500      55500   TABLE ACCESS FULL CUSTOMERS (cr=1964 pr=0 pw=0 time=120870 us starts=1 cost=405 size=666000 card=55500)

Elapsed times include waiting on following events:
  Event waited on                             Times   Max. Wait  Total Waited
  ----------------------------------------   Waited  ----------  ------------
  PGA memory operation                          35        0.00          0.00
  Disk file operations I/O                       1        0.00          0.00
  SQL*Net message to client                    542        0.00          0.00
  SQL*Net message from client                  542       41.10         57.47
********************************************************************************

问题1:未执行更新操作,为何存在28次current mode block reads?

别被current mode的名字误导——这种读取可不是DML操作的专属!Oracle在执行查询时,也会因为访问数据字典或段元数据块触发current读,因为这些块需要最新的状态,不需要生成一致性快照。

看你的执行计划,SALES是分区表,刚好覆盖1-28号分区。每次访问一个分区,Oracle都需要读取该分区的段头块(用来获取分区的存储布局、extent分布等核心信息),而段头块的读取就是current模式的。28个分区刚好对应28次current reads,这个数字完全吻合。

另外,PGA操作中的临时段管理也可能产生少量current读,但这里的数量和分区数完美匹配,所以分区段头读取是最直接的原因。

问题2:执行计划中部分步骤starts值为0,但Autotrace显示这些步骤已执行,请问这些步骤是否实际执行?若已执行,为何starts值为0?

这些starts=0的步骤完全没有执行——它们是优化器生成的备选执行分支,实际运行时Oracle选择了另一条更高效的路径。

比如你看到的INDEX UNIQUE SCAN CUSTOMERS_PK和对应的表访问步骤,是优化器考虑的“通过主键索引关联CUSTOMERS表”的方案,但实际执行时,优化器选择了用HASH JOIN直接关联全表扫描的CUSTOMERS(看执行计划最底部的TABLE ACCESS FULL CUSTOMERS,starts=1,还有cr=1964的实际读取统计)。

至于Autotrace显示这些步骤,是因为Autotrace输出的是优化器生成的完整计划树(包含所有可能的候选路径),而TKPROF的starts是实际运行时的执行统计——只有真正走的分支才会有starts>0的记录。

问题3:为何单次查询同时存在硬解析和软解析(共两次解析)?

先看你的TKPROF输出:Parse count=1,Misses in library cache during parse:1——这说明主查询只触发了1次硬解析,根本没有软解析。

如果你觉得有两次解析,大概率是把主查询的解析和Oracle内部的递归SQL解析混在一起了。当执行你的查询时,Oracle会自动运行一些递归SQL(比如查询数据字典获取分区信息、表的统计信息、权限验证等),这些递归SQL也会经历解析过程(可能是硬解析或软解析)。你可能在某个工具(比如Autotrace的详细输出)里看到了这些递归SQL的解析记录,误以为是主查询的两次解析。

简单总结:主查询本身只有1次硬解析,“两次解析”的错觉来自Oracle内部递归SQL的解析操作。


内容的提问来源于stack exchange,提问作者oramas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:35:40