[20250815]关于CPU成本计算(补充)2.txt

[20250815]关于CPU成本计算(补充)2.txt

--//以前测试过,当时一边做一边猜测,反推X,Y,Z的值,有点乱,做一些必要的整理,补充索引的一些测试。
--//看Jonathan Lewis的<基于成本的Oracle优化法则>,里面提到P51:

Finding out exactly where the original count of 72,914,400 operations came from is much
harder. If you care to run through a set of extremely tedious experiments, you could probably
track it down—approximately—to details like these:
. Cost of acquiring a block = X
. Cost of locating a row in a block = Y
. Cost of acquiring the Nth (in our case the 2nd) column in a row = (N - 1) * Z
. Cost of comparing a numeric column with a numeric constant = A

--//每块的CPU COST X=7121.44。
--//每行的CPU COST Y=150
--//每列的CPU COST Z=20,注意计算Highest_column_id
--//谓词部分使用常量比较成本 A=50
--//谓词部分使用绑定变量比较成本 A=150。
--//补充谓词部分字段参与运算成本的情况,每增加1个字段增加50,或者增加一个运算增加50.
--//以前测试在谓词使用函数存在问题,各种函数的成本并不是固定,另外写一篇blog说明。
--//扫描唯一索引块成本  1050。

--//里面的X,Y,Z值很容易确定,后面的测试有一些混乱,重新做1次,以前的测试参考:[20190821]关于CPU成本计算.txt

1.环境:
SCOTT@book01p> @ver2
==============================
PORT_STRING                   : x86_64/Linux 2.4.xx
VERSION                       : 21.0.0.0.0
BANNER                        : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
BANNER_FULL                   : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
BANNER_LEGACY                 : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
CON_ID                        : 0
PL/SQL procedure successfully completed.

2.测试1:

SCOTT@book01p> create table t as select rownum a1 , rownum a2 ,rownum a3 from dual connect by level<=100 ;
Table created.
--//分析表略。

SCOTT@book01p> select blocks,num_rows from user_tables where table_name='T';
    BLOCKS   NUM_ROWS
---------- ----------
         4        100

column STATEMENT_ID format a10
column OPTIONS format a10
column time format  9999
explain plan set statement_id='a1' for select 1 from t where a1=1;
explain plan set statement_id='a2' for select 1 from t where a2=1;
explain plan set statement_id='a3' for select 1 from t where a3=1;
explain plan set statement_id='a1x' for select 1 from t where a1=:N1;
explain plan set statement_id='a2x' for select 1 from t where a2=:N1;
explain plan set statement_id='a3x' for select 1 from t where a3=:N1;

SCOTT@book01p> select STATEMENT_ID,OPERATION, OPTIONS, COST, CPU_COST, IO_COST, TIME from plan_table where options='FULL';
STATEMENT_ OPERATION                      OPTIONS          COST   CPU_COST    IO_COST  TIME
---------- ------------------------------ ---------- ---------- ---------- ---------- -----
a1         TABLE ACCESS                   FULL                3      48486          3     1
a2         TABLE ACCESS                   FULL                3      50486          3     1
a3         TABLE ACCESS                   FULL                3      52486          3     1
a1x        TABLE ACCESS                   FULL                3      58486          3     1
a2x        TABLE ACCESS                   FULL                3      60486          3     1
a3x        TABLE ACCESS                   FULL                3      62486          3     1
6 rows selected.

--//select部分cost,没有查询字段。
7121.44 * blocks + 150*rows + 20*rows* ( Highest_column_id - Lowest_column_id)
= 7121.44 * 4 + 150*100 + 20*150*(1-1) = 43485.76 =  43486

--//可以发现where中cost对比如下:
--//使用非绑定变量的情况:
a1=1   48486-43486 = 5000
a2=1   50486-43486 = 7000
a3=1   52486-43486 = 9000
--//使用绑定变量的情况:
a1=:N1 58486-43486 = 15000
a2=:N1 60486-43486 = 17000
a3=:N1 62486-43486 = 19000

--//使用非绑定变量的情况:
--//对应a1=100条件,表T共用100条记录,对比100次,这样每次比较5000/100 = 50.
--//以此类推a2=100,每次7000/100 = 70.a3=100,每次9000/100 = 90.
--//结合前面的Z=20(20 CPU Cycles for Column Skip).where的cost实际上的计算公式如下:

rows*50+rows*((Highest_column_id-1)*20).

--//实际上可以理解每次比较的cpu cost是50. 也就是可以 A=50.

--//使用绑定变量的情况:
--//与前面类似,很容易推导使用绑定变量每次比较的CPU COST = 150.

--//注真实的情况也许很复杂,也许谓词存在and 或者 or ,这样我估计oracle优先选择在选择性很好的字段做比较。
--//参考:[20190821]关于CPU成本计算.txt,里面有一些更复杂的测试。

3.测试2:
--//测试谓词使用函数的情况,推断使用函数的cpu cost。
--//测试前退出在登录,因为查询plan_table是临时表。

column STATEMENT_ID format a10
column OPTIONS format a10
column time format  9999
explain plan set statement_id='a1' for select 1 from t where to_char(a1)='1';
explain plan set statement_id='a2' for select 1 from t where to_char(a2)='1';
explain plan set statement_id='a3' for select 1 from t where to_char(a3)='1';
explain plan set statement_id='a1x' for select 1 from t where to_char(a1)=:N1;
explain plan set statement_id='a2x' for select 1 from t where to_char(a2)=:N1;
explain plan set statement_id='a3x' for select 1 from t where to_char(a3)=:N1;

SCOTT@book01p> select STATEMENT_ID,OPERATION, OPTIONS, COST, CPU_COST, IO_COST, TIME from plan_table where options='FULL';
STATEMENT_ OPERATION                      OPTIONS          COST   CPU_COST    IO_COST  TIME
---------- ------------------------------ ---------- ---------- ---------- ---------- -----
a1         TABLE ACCESS                   FULL                3      58486          3     1
a2         TABLE ACCESS                   FULL                3      60486          3     1
a3         TABLE ACCESS                   FULL                3      62486          3     1
a1x        TABLE ACCESS                   FULL                3      58486          3     1
a2x        TABLE ACCESS                   FULL                3      60486          3     1
a3x        TABLE ACCESS                   FULL                3      62486          3     1
6 rows selected.

--//select部分cost,没有查询字段。
7121.44 * blocks + 150*rows + 20*rows* ( Highest_column_id - Lowest_column_id)
= 7121.44 * 4 + 150*100 + 20*150*(1-1) = 43485.76 =  43486

--//可以发现where中cost对比如下:
--//使用非绑定变量的情况:
to_char(a1)='1'  58486-43486 = 15000
to_char(a2)='1'  60486-43486 = 17000
to_char(a3)='1'  62486-43486 = 19000

--//使用绑定变量的情况:
to_char(a1)=:N1; 58486-43486 = 15000
to_char(a2)=:N1; 60486-43486 = 17000
to_char(a3)=:N1; 62486-43486 = 19000

--//可以发现where中cost对比如下:
to_char(a1)='1' 58486-43486 = 15000
to_char(a2)='1' 60486-43486 = 17000
to_char(a3)='1' 62486-43486 = 19000

--//对应a1=100条件,表T共用100条记录,对比100次,这样每次 15000/100  = 150.
--//以此类推a2=100,每次17000/100 = 170.a3=100,每次19000/100 = 190.
--//根据前面的测试,排除字段的成本(20),比较每次50,可以推断函数部分占100,感觉这部分也太少了!!
--//字段= 常量的比较每次50,而引入函数仅仅增加100。我个人感觉oracle设置太小了,应该设置500.

--//注:我一直以为所有的函数的成本都是一样的,实际的情况各个函数不同,另外写一篇blog说明,我这里的测试使用to_char实际上
--//是使用函数里面最小的情况。

--//换一个测试方法:
SCOTT@book01p> explain plan set statement_id='xxx' for select to_char(a1) from t where rownum=1;
Explained.

SCOTT@book01p> select STATEMENT_ID,OPERATION, OPTIONS, COST, CPU_COST, IO_COST, TIME from plan_table where statement_id='xxx';
STATEMENT_ OPERATION                      OPTIONS          COST   CPU_COST    IO_COST  TIME
---------- ------------------------------ ---------- ---------- ---------- ---------- -----
xxx        SELECT STATEMENT                                   2       7271          2     1
xxx        COUNT                          STOPKEY
xxx        TABLE ACCESS                   FULL                2       7271          2     1

--//select部分:
7121.44 * blocks + 150*rows + 20*rows* ( Highest_column_id - 1)
= 7121.44 * 1 + 150*1   = 7271.44
--//在select出现的函数不计算cost。

4.测试3:
--//测试谓词部分字段运算成本,这部分以前没有测试过。

column STATEMENT_ID format a16
column OPTIONS format a10
column time format  9999
explain plan set statement_id='A1+1'         for select 1 from t where a1+1=100;
explain plan set statement_id='A1+A1'        for select 1 from t where a1+a1=100;
explain plan set statement_id='A1+A2'        for select 1 from t where a1+a2=100;
explain plan set statement_id='A1+A2*2'      for select 1 from t where a1+a2*2=100;
explain plan set statement_id='A1+A2+A3'     for select 1 from t where A1+A2+A3=100;
explain plan set statement_id='power(A1)+A2' for select 1 from t where power(A1,2)+A2=100;

explain plan set statement_id='XA1+1'         for select 1 from t where a1+1=:N1;
explain plan set statement_id='XA1+A1'        for select 1 from t where a1+a1=:N1;
explain plan set statement_id='XA1+A2'        for select 1 from t where a1+a2=:N1;
explain plan set statement_id='XA1+A2*2'      for select 1 from t where a1+a2*2=:N1;
explain plan set statement_id='XA1+A2+A3'     for select 1 from t where A1+A2+A3=:N1;
explain plan set statement_id='Xpower(A1)+A2' for select 1 from t where power(A1,2)+A2=:N1;

SCOTT@book01p> select STATEMENT_ID,OPERATION, OPTIONS, COST, CPU_COST, IO_COST, TIME from plan_table where options='FULL';
STATEMENT_ID     OPERATION                      OPTIONS          COST   CPU_COST    IO_COST  TIME
---------------- ------------------------------ ---------- ---------- ---------- ---------- -----
A1+1             TABLE ACCESS                   FULL                3      53486          3     1
A1+A1            TABLE ACCESS                   FULL                3      53486          3     1
A1+A2            TABLE ACCESS                   FULL                3      55486          3     1
A1+A2*2          TABLE ACCESS                   FULL                3      60486          3     1
A1+A2+A3         TABLE ACCESS                   FULL                3      62486          3     1
power(A1)+A2     TABLE ACCESS                   FULL                3      80486          3     1
XA1+1            TABLE ACCESS                   FULL                3      63486          3     1
XA1+A1           TABLE ACCESS                   FULL                3      63486          3     1
XA1+A2           TABLE ACCESS                   FULL                3      65486          3     1
XA1+A2*2         TABLE ACCESS                   FULL                3      70486          3     1
XA1+A2+A3        TABLE ACCESS                   FULL                3      72486          3     1
Xpower(A1)+A2    TABLE ACCESS                   FULL                3      90486          3     1
12 rows selected.

--//select部分cost,没有查询字段。
7121.44 * blocks + 150*rows + 20*rows* ( Highest_column_id - Lowest_column_id)
= 7121.44 * 4 + 150*100 + 20*150*(1-1) = 43485.76 =  43486

--//可以发现where中cost对比如下:
--//使用非绑定变量的情况:
A1+1           53486 - 43486  = 10000
A1+A1          53486 - 43486  = 10000
A1+A2          55486 - 43486  = 12000
A1+A2*2        60486 - 43486  = 17000
A1+A2+A3       62486 - 43486  = 19000
power(A1)+A2   80486 - 43486  = 37000

--//带运算比较的起点是100,有字段参与运算,oracle并不像函数那样A=150. 而是根据运算的不同发生一些变化。
--//注意排序字段成本每个20.
A1+1          100
A1+A1         100
A1+A2         100
A1+A2*2       150
A1+A2+A3      150
power(A1)+A2  350

--//使用绑定变量的情况:
XA1+1           63486 - 43486 = 20000
XA1+A1          63486 - 43486 = 20000
XA1+A2          65486 - 43486 = 22000
XA1+A2*2        70486 - 43486 = 27000
XA1+A2+A3       72486 - 43486 = 29000
Xpower(A1)+A2   90486 - 43486 = 47000
--//对比前面非绑定变量的情况,每个总的增加10000,也就是每次比较比非绑定变量增加100.
--//注意排序字段成本每个20.

XA1+1            200
XA1+A1           200
XA1+A2           200
XA1+A2*2         250
XA1+A2+A3        250
Xpower(A1)+A2    450

--//还是简单看出一些规律,比如增加1个简单运算增50,是否各个函数有关cost,oracle内部存在定义,power(A1,2)定义300.
--//也许前面测试使用to_char函数定义很低。
--//采用绑定变量增100.

--//补充测试:
column STATEMENT_ID format a10
column OPTIONS format a10
column time format  9999
explain plan set statement_id='p1' for select 1 from t where power(A1,2)=100;
explain plan set statement_id='p2' for select 1 from t where power(A1,2)=:N1;

explain plan set statement_id='s1' for select 1 from t where sqrt(A1)=100;
explain plan set statement_id='s2' for select 1 from t where sqrt(A1)=:N1;

SCOTT@book01p> select STATEMENT_ID,OPERATION, OPTIONS, COST, CPU_COST, IO_COST, TIME from plan_table where options='FULL';
STATEMENT_ID     OPERATION                      OPTIONS          COST   CPU_COST    IO_COST  TIME
---------------- ------------------------------ ---------- ---------- ---------- ---------- -----
p1               TABLE ACCESS                   FULL                3      73486          3     1
p2               TABLE ACCESS                   FULL                3      83486          3     1
s1               TABLE ACCESS                   FULL                3      68486          3     1
s2               TABLE ACCESS                   FULL                3      78486          3     1

power(A1,2)=100;  73486-43486 = 30000
power(A1,2)=:N1;  83486-43486 = 40000
sqrt(A1)=100;     68486-43486 = 25000
sqrt(A1)=:N1;     78486-43486 = 35000
--//看来oracle每个函数的定义都不相同。

explain plan set statement_id='q1' for select power(a1,2) from t where rownum=1;
explain plan set statement_id='q2' for select sqrt(a1) from t where rownum=1;

SCOTT@book01p> select STATEMENT_ID,OPERATION, OPTIONS, COST, CPU_COST, IO_COST, TIME from plan_table where options='FULL' and STATEMENT_ID like 'q%';

STATEMENT_ID     OPERATION                      OPTIONS          COST   CPU_COST    IO_COST  TIME
---------------- ------------------------------ ---------- ---------- ---------- ---------- -----
q1               TABLE ACCESS                   FULL                2       7271          2     1
q2               TABLE ACCESS                   FULL                2       7271          2     1

--//select部分:
7121.44 * blocks + 150*rows + 20*rows* ( Highest_column_id - 1)
= 7121.44 * 1 + 150*1   = 7271.44
--//在select出现的函数不计算cost。

5.测试4:
--//建立索引看看。

SCOTT@book01p> create unique index i_t_a3  on t(a3);
Index created.

SCOTT@book01p> create  index i_t_a2  on t(a2);
Index created.

column STATEMENT_ID format a10
column OPTIONS format a12
column time format  9999
explain plan set statement_id='b2'  for select 1 from t where a2 = 50;
explain plan set statement_id='b3'  for select 1 from t where a3 = 50;
explain plan set statement_id='b2x' for select 1 from t where a2 = :N1;
explain plan set statement_id='b3x' for select 1 from t where a3 = :N1;

SCOTT@book01p> column OPTIONS format a12
SCOTT@book01p> select STATEMENT_ID,OPERATION, OPTIONS, COST, CPU_COST, IO_COST, TIME from plan_table where OPERATION='INDEX';
STATEMENT_ OPERATION                      OPTIONS            COST   CPU_COST    IO_COST  TIME
---------- ------------------------------ ------------ ---------- ---------- ---------- -----
b2         INDEX                          RANGE SCAN            1       7321          1     1
b3         INDEX                          UNIQUE SCAN           0       1050          0     1
b2x        INDEX                          RANGE SCAN            1       7321          1     1
b3x        INDEX                          UNIQUE SCAN           0       1050          0     1

--//RANGE SCAN , UNIQUE SCAN 不同,前者7321. 后者1050.

explain plan set statement_id='b2'  for select 1 from t where a2 = 50;
--//select部分:
7121.44 * blocks + 150*rows + 20*rows* ( Highest_column_id - 1)
7121.44 * 0 + 150*0   = 0

--//索引部分,实际上与数据块类似,可以想象索引就是仅仅包含索引字段的表,如果不是唯一索引与数据块类似。
7121.44 * blocks + 150*rows + 50*compare_counts
7121.44 * 1 + 150*1   = 7271.44
--//比较部分成本1次:50
7271.44+50 = 7321.44

explain plan set statement_id='b3'  for select 1 from t where a3 = 50;
--//select部分:
7121.44 * blocks + 150*rows + 20*rows* ( Highest_column_id - 1)
7121.44 * 0 + 150*0   = 0
--//比较部分成本1次:50
--//这样扫描索引块的成本就是1000.

--//继续探究索引的如何计算:
column STATEMENT_ID format a10
column OPTIONS format a12
column time format  9999

explain plan set statement_id='c1'  for select 1 from t where a3 between 1 and 1;
explain plan set statement_id='c2'  for select 1 from t where a3 between 1 and 2;
explain plan set statement_id='c3'  for select 1 from t where a3 between 1 and 3;
explain plan set statement_id='c4'  for select 1 from t where a3 between 1 and 4;
explain plan set statement_id='c5'  for select 1 from t where a3 between 1 and 5;
explain plan set statement_id='c6'  for select 1 from t where a3 between 1 and 6;
explain plan set statement_id='c7'  for select 1 from t where a3 between 1 and 7;
explain plan set statement_id='c8'  for select 1 from t where a3 between 1 and 8;
explain plan set statement_id='c9'  for select 1 from t where a3 between 1 and 9;

SCOTT@book01p> select STATEMENT_ID,OPERATION, OPTIONS, COST, CPU_COST, IO_COST, TIME from plan_table where STATEMENT_ID like 'c%' and OPERATION='INDEX';
STATEMENT_ OPERATION                      OPTIONS            COST   CPU_COST    IO_COST  TIME
---------- ------------------------------ ------------ ---------- ---------- ---------- -----
c1         INDEX                          UNIQUE SCAN           0       1050          0     1
c2         INDEX                          RANGE SCAN            1       7721          1     1
c3         INDEX                          RANGE SCAN            1       7921          1     1
c4         INDEX                          RANGE SCAN            1       8121          1     1
c5         INDEX                          RANGE SCAN            1       8321          1     1
c6         INDEX                          RANGE SCAN            1       8521          1     1
c7         INDEX                          RANGE SCAN            1       8721          1     1
c8         INDEX                          RANGE SCAN            1       8921          1     1
c9         INDEX                          RANGE SCAN            1       9121          1     1
9 rows selected.
--//a3 between 1 and 1智能判断使用UNIQUE SCAN,而RANGE SCAN,每次增加1,查询的cost增加200.

--//explain plan set statement_id='c2'  for select 1 from t where a3 between 1 and 2;
--//7721-7121 = 600 ,增加600.
--//你可以想象索引就是仅仅包含索引字段的表,a3 between 1 and 2相当于比较3次。
--//按照情况,扫描索引数据块1,3行,比较3次来计算。
7121.44 * blocks + 150*rows + 50*compare_counts
7121.44 * 1 + 150*3 + 20*rows* ( 1 - 1) + 50*3 = 7721.44

--//仅仅对于唯一索引扫描不同其CPU COST成本 1000+50。

6.补充一些例子说明问题:
SCOTT@book01p> column OPTIONS format a30
SCOTT@book01p> explain plan set statement_id='e3'  for select a3 from t where a2 = 50;
Explained.

SCOTT@book01p> select STATEMENT_ID,OPERATION, OPTIONS, COST, CPU_COST, IO_COST, TIME from plan_table where STATEMENT_ID like 'e3';
STATEMENT_ OPERATION                      OPTIONS                              COST   CPU_COST    IO_COST  TIME
---------- ------------------------------ ------------------------------ ---------- ---------- ---------- -----
e3         SELECT STATEMENT                                                       2      14633          2     1
e3         TABLE ACCESS                   BY INDEX ROWID BATCHED                  2      14633          2     1
e3         INDEX                          RANGE SCAN                              1       7321          1     1

--//索引部分:
7121.44 * blocks + 150*rows + 50*compare_counts
7121.44 * 1 + 150*1 + 50*1 = 7321.44
--//select部分:
7121.44 * blocks + 150*rows + 20*rows* ( Highest_column_id - Lowest_column_id)
==7121.44 * 1 + 150*1 + 20*1* (3-1)
=7311.44
--//7321.44+7311.44 = 14632.88
--//取整正好是14633

--//删除索引。
SCOTT@book01p> drop index i_t_a3;
Index dropped.

SCOTT@book01p> drop index i_t_a2;
Index dropped.

SCOTT@book01p> explain plan set statement_id='e4'  for select a2 from t where a3 = 50;
Explained.

SCOTT@book01p> select STATEMENT_ID,OPERATION, OPTIONS, COST, CPU_COST, IO_COST, TIME from plan_table where STATEMENT_ID like 'e4';
STATEMENT_ OPERATION                      OPTIONS                              COST   CPU_COST    IO_COST  TIME
---------- ------------------------------ ------------------------------ ---------- ---------- ---------- -----
e4         SELECT STATEMENT                                                       3      52486          3     1
e4         TABLE ACCESS                   FULL                                    3      52486          3     1

--//谓词比较部分:
--//比较100次,这样比较cost 50*100 = 5000
--//select部分:
7121.44 * blocks + 150*rows + 20*rows* ( Highest_column_id - Lowest_column_id)
=7121.44 * 4 + 150*100 + 20*100* (3-1)
=47485.76

--//47485.76+5000 = 52485.76
--//注意Highest_column_id =3,因为where a3 = 50。

--//重复以前的1个例子:
SCOTT@book01p> explain plan set statement_id='bb' for select a3 from t where a2=100 ;
Explained.

SCOTT@book01p> select STATEMENT_ID,OPERATION, OPTIONS, COST, CPU_COST, IO_COST, TIME from plan_table where STATEMENT_ID='bb';
STATEMENT_ OPERATION        OPTIONS COST CPU_COST IO_COST TIME
---------- ---------------- ------- ---- -------- ------- ----
bb         SELECT STATEMENT            3    50506       3    1
bb         TABLE ACCESS     FULL       3    50506       3    1

--//我先说说我的理解然后计算:
--//如果查询时第1条记录是a2=1,这样根本不用取a3字段直接跳过这条记录,这样select部分仅仅取a2后然后比较
--//如果a2=100符合查询条件再取字段a3.有了这样理解cpu cost计算就简单了.

--//select部分,开始仅仅需要取到a2字段(即使select部分包含a3):
7121.44 * blocks + 150*rows + 20*rows* (Highest_column_id - Lowest_column_id)
7121.44 * 4 + 150*100 + 20*rows* ( 2 - 1)  = 43485.76 + 2000 = 45486

--//where部分:
比较100次 100*50=5000
仅仅1条符合a2=100.取a3字段成本 :
20*rows* (Highest_column_id - Lowest_column_id)
20*1*(3-2) = 20

--//cpu cost
45486 + 5000+ 20 = 50506
--//完全符合.
--//补充说明:字段成本分2次计算
--//第一次是 20*rows* ( Highest_column - Lowest_column) ,这里的Highest_column=2,Lowest_column=1.rows=100.
--//第二次是 20*rows* ( Highest_column - Lowest_column) ,这里的Highest_column=3,Lowest_column=2.rows=1.
--//总之字段成本要看select以及查询条件结合起来判断,出现的情况可能比较复杂.

6.再补充索引的情况:
--//删除前面建立的索引。
SCOTT@book01p> create index i_t_a3_a2 on t(a3,a2);
Index created.

SCOTT@book01p> explain plan set statement_id='f1'  for select a1 from t where a3 = 50;
Explained.

SCOTT@book01p> select STATEMENT_ID,OPERATION, OPTIONS, COST, CPU_COST, IO_COST, TIME from plan_table where STATEMENT_ID like 'f1%';
STATEMENT_ID     OPERATION                      OPTIONS                       COST   CPU_COST    IO_COST  TIME
---------------- ------------------------------ ----------------------- ---------- ---------- ---------- -----
f1               SELECT STATEMENT                                                2      14633          2     1
f1               TABLE ACCESS                   BY INDEX ROWID BATCHED           2      14633          2     1
f1               INDEX                          RANGE SCAN                       1       7321          1     1

--//分开2部分计算:
--//索引部分:
7121.44 * blocks + 150*rows + 20*rows* (Highest_column_id - Lowest_column_id)
7121.44+150+0 = 7271.44
--//比较1次 50
7271.44+50 = 7321.44
--//注意在索引a3是第1个字段。

--//select部分:
7121.44 * blocks + 150*rows + 20*rows* (Highest_column_id - Lowest_column_id)
7121.44+150+0 = 7271.44

7271.44+7321.44 = 14592.88

--//可以发现我的计算对不上,相差14633-14593 = 40。似乎取到A3字段。

7.总结:
--//首先以上大部分内容完全是先有cpu cost,再反推数值,也许内部的计算更复杂。

--//大概还是存在一些规律:

--//每块的CPU COST X=7121.44。
--//每行的CPU COST Y=150
--//每列的CPU COST Z=20,注意计算Highest_column_id

--//谓词部分使用常量比较成本 A=50 ,引入函数比较成本每个函数的成本不同!!
--//谓词部分使用绑定变量比较成本再增加 100。

--//补充谓词部分字段运算成本,每增加1个字段增加50,增加运算50.
--//扫描唯一索引块成本      1050。
--//在select出现的函数不计算cost。

--//CPU COST计算分成几个部分:

--//扫描块数量的成本  
--//扫描行数量的成本  
--//扫描字段的成本,取决于字段在段的位置。
--//建议反复看看explain plan set statement_id='bb' for select a3 from t where a2=100 ;的例子
--//可以理解分2部分。

--//谓词比较成本,50起步,增加1个运算增50,增加1个字段增50。注:仅仅是我上面观察到的结果。
--//谓词部分使用绑定变量比较成本再增加 100。

--//索引部分的情况类似,你可以把索引想象为包含索引字段的表,与数据块部分分开计算。
--//特殊的情况是唯一索引扫描,块的成本是1050.



posted @ 2025-08-19 20:13  lfree  阅读(4)  评论(0)    收藏  举报