[20190821]关于CPU成本计算.txt
[20190821]关于cpu成本计算.txt
--//有人问链接http://blog.itpub.net/267265/viewspace-2653964/中cpu成本如何计算的,实际上一般在优化中考虑这个细节很少,
--//因为cpu cost占整个cost的比例很少,至于如何计算说复杂很复杂,说简单也很简单.
--//如果你看onathan 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
--//通过值计算这些成本比较困难,实际上反推可以很容易的,我以前做过系列blog,可惜现在找不到了.
--//大概做一遍,实际的情况也许很复杂..^_^.
1.环境:
scott@test01p> @ ver1
port_string version banner con_id
-------------------- ---------- ---------------------------------------------------------------------------- ------
ibmpc/win_nt64-9.1.0 12.2.0.1.0 oracle database 12c enterprise edition release 12.2.0.1.0 - 64bit production 0
2.测试:
scott@test01p> create table t as select rownum a1 , rownum a2 ,rownum a3 from dual connect by level<=100 ;
table created.
--//分析略.
column statement_id format a10
column options format a10
explain plan set statement_id='a1' for select a1 from t where rownum<=1;
explain plan set statement_id='a2' for select a2 from t where rownum<=1;
explain plan set statement_id='a3' for select a3 from t where rownum<=1;
scott@test01p> 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 2 7271 2 1
a2 table access full 2 7291 2 1
a3 table access full 2 7311 2 1
--//从这里就可以看出7271,7291,7311正好相差20 ,也就是 20 cpu cycles for column skip. 也就是上面提到z=20.
3.测试,分别取同一的字段a1,并且仅仅取1行,2行,3行的情况:
--//退出上面的测试,因为plan_table是临时表,退出后自动清空.
--//我建立的表很小,数据自然在1个块中.
--//select 'explain plan set statement_id='''||lpad(rownum,3,'0')||''''||' for select a1 from t where rownum<='||rownum||';' c80 from t;
select 'explain plan set statement_id='''||lpad(rownum,3,'0')||''''||' for select 1 from t where rownum<='||rownum||';' c80 from t;
--//把以上的输出保存一个文件执行:
scott@test01p> 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
---------- ------------ ------- ---- -------- ------- ----
001 table access full 2 7271 2 1
002 table access full 2 7421 2 1
003 table access full 2 7571 2 1
004 table access full 2 7721 2 1
005 table access full 2 7871 2 1
006 table access full 2 8021 2 1
007 table access full 2 8321 2 1
008 table access full 2 8321 2 1
009 table access full 2 8471 2 1
010 table access full 2 8621 2 1
011 table access full 2 8771 2 1
012 table access full 2 8921 2 1
...
092 table access full 3 42286 3 1
093 table access full 3 42436 3 1
094 table access full 3 42586 3 1
095 table access full 3 42736 3 1
096 table access full 3 42886 3 1
097 table access full 3 43036 3 1
098 table access full 3 43186 3 1
099 table access full 3 43486 3 1
100 table access full 3 43486 3 1
100 rows selected.
statement_ cpu_cost n1 n2
---------- -------- ----- ----
001 7271 7421 150
002 7421 7571 150
003 7571 7721 150
004 7721 7871 150
005 7871 8021 150
006 8021 8321 300
007 8321 8321 0
008 8321 8471 150
009 8471 8621 150
010 8621 8771 150
011 8771 8921 150
012 8921 9071 150
013 9071 9371 300
014 9371 9371 0
015 9371 9521 150
016 9521 9671 150
017 9671 9821 150
018 9821 9971 150
019 9971 10121 150
020 10121 10271 150
021 10271 10421 150
022 10421 10571 150
023 10571 10721 150
024 10721 10871 150
025 10871 18143 7272
026 18143 18293 150
027 18293 18593 300
028 18593 18593 0
029 18593 18743 150
030 18743 18893 150
031 18893 19043 150
032 19043 19193 150
033 19193 19343 150
034 19343 19493 150
035 19493 19643 150
036 19643 19793 150
037 19793 19943 150
038 19943 20093 150
039 20093 20243 150
040 20243 20393 150
041 20393 20543 150
042 20543 20693 150
043 20693 20843 150
044 20843 20993 150
045 20993 21143 150
046 21143 21293 150
047 21293 21443 150
048 21443 21593 150
049 21593 21743 150
050 21743 29014 7271
051 29014 29164 150
052 29164 29314 150
053 29314 29464 150
054 29464 29914 450
055 29914 29914 0
056 29914 29914 0
057 29914 30064 150
058 30064 30214 150
059 30214 30364 150
060 30364 30514 150
061 30514 30664 150
062 30664 30814 150
063 30814 30964 150
064 30964 31114 150
065 31114 31264 150
066 31264 31414 150
067 31414 31564 150
068 31564 31714 150
069 31714 31864 150
070 31864 32014 150
071 32014 32164 150
072 32164 32314 150
073 32314 32464 150
074 32464 32614 150
075 32614 39886 7272
076 39886 40036 150
077 40036 40186 150
078 40186 40336 150
079 40336 40486 150
080 40486 40636 150
081 40636 40786 150
082 40786 40936 150
083 40936 41086 150
084 41086 41236 150
085 41236 41386 150
086 41386 41536 150
087 41536 41686 150
088 41686 41836 150
089 41836 41986 150
090 41986 42136 150
091 42136 42286 150
092 42286 42436 150
093 42436 42586 150
094 42586 42736 150
095 42736 42886 150
096 42886 43036 150
097 43036 43186 150
098 43186 43486 300
099 43486 43486 0
100 43486
100 rows selected.
--//我一直不理解这里为什么出现跳跃.不过还是基本可以定位cost of locating a row in a block = y = 150.
--//也许是后面where条件的影响.
--//后记:
--//在statement_id=025,050,075,n2分别是7272,7271,7272.说明在statement_id=026,051,076多访问1块。
--//可以这么理解表t占4blocks,共100行,平均下来每块25行。这样当查询等于rownum<=26,51,76时出现多访问1块的情况。
--//当然实际的情况不是这样^_^。
scott@test01p> select blocks,num_rows from user_tables where table_name='t';
blocks num_rows
---------- ----------
4 100
--//但是n2=300,450的跳跃情况我实在无法解析,不知道那位能解析看看。
4.继续分析:
--//多个字段在select的情况呢?
column statement_id format a10
column options format a10
explain plan set statement_id='a0' for select 1 from t where rownum<=1;
explain plan set statement_id='ax' for select rowid from t where rownum<=1;
explain plan set statement_id='a1' for select a1 from t where rownum<=1;
explain plan set statement_id='a2' for select a2 from t where rownum<=1;
explain plan set statement_id='a3' for select a3 from t where rownum<=1;
explain plan set statement_id='a12' for select a1,a2 from t where rownum<=1;
explain plan set statement_id='a13' for select a1,a3 from t where rownum<=1;
explain plan set statement_id='a23' for select a2,a3 from t where rownum<=1;
explain plan set statement_id='a123' for select a1,a2,a3 from t where rownum<=1;
scott@test01p> 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
---------- ------------ ------- ---- -------- ------- ----
a0 table access full 2 7271 2 1
ax table access full 2 7271 2 1
a1 table access full 2 7271 2 1
a2 table access full 2 7291 2 1
a3 table access full 2 7311 2 1
a12 table access full 2 7291 2 1
a13 table access full 2 7311 2 1
a23 table access full 2 7311 2 1
a123 table access full 2 7311 2 1
9 rows selected.
--//看statement_id=a0,ax,a1可以发现cpu_cost都是一样,也就是取表中第一个字段不计cpu cost.
--//看statement_id= a2,a12 ,cpu_cost=7291也说明取表中第一个字段不计cpu cost.
--//也就是前面的 cost of acquiring the nth (in our case the 2nd) column in a row = (n - 1) * z
--//另外你可以发现看statement_id= a3,a13,a23,a123 中 cpu_cost=7311,也就是select中列的成本以最大列的成本计算.
--//剩下的就是上面x(cost of acquiring a block)如何计算。实际上只要反推就可以知道x等于多少,x= 7271-150 = 7121.
--//实际上后面还有小数点的,为了后面的测试需要准确的知道小数点后的数值是多少,继续测试。
5.hack统计信息看看.
--//为了准确确定x(cost of acquiring a block),hack统计信息,增加表t块的数量。
scott@test01p> exec dbms_stats.set_table_stats(user,'t',numblks=>1000000);
pl/sql procedure successfully completed.
scott@test01p> alter system flush shared_pool;
system altered.
scott@test01p> explain plan set statement_id='block' for select a1 from t ;
explained.
scott@test01p> 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
---------- ------------ ------- ------ ---------- ------- ----
block table access full 271400 7121455000 270835 11
--//注:没有修改记录数量还是100.这样计算如下:
--//(7121455000-100*150)/1000000 = 7121.44,也就是前面x=7121.44,这样就获得x的精确值。
--//当做到这里时,我一直想oracle内部如何定下x=7121.44,后面居然还有小数点...
--//这样就知道select部分的计算公式;
x*blocks +( y+(n - 1) * z )*numrows
7121.44 * blocks + 150*rows + 20*effect_rows* (highest_column_id - lowest_column_id)
--//注:lowest_column_id许多情况下等于1,我之所以改动公式,继续看后面的的测试就知道了。实际上lowest_column_id=1是没有
--//where查询条件的特例.
--//而且许多情况下字段成本要单独计算.我这里定义为effect_rows,如果没有where条件实际上等于前面rows.
--//简单验证看看:
scott@test01p> explain plan set statement_id='dept' for select * from dept;
explained.
scott@test01p> select statement_id,operation, options, cost, cpu_cost, io_cost, time from plan_table where statement_id='dept';
statement_ operation options cost cpu_cost io_cost time
---------- ---------------- ------- ---- -------- ------- ----
dept select statement 3 36367 3 1
dept table access full 3 36367 3 1
scott@test01p> select blocks,num_rows from user_tables where table_name='dept';
blocks num_rows
------ --------
5 4
7121.44 * blocks + 150*rows + 20*rows* (highest_column_id - lowest_column_id)
= 7121.44 * 5 + 150*4 + 20*4*(3-1) = 36367.20
--//基本吻合.
6.最后看看谓词部分a:
--//如果有where查询条件呢?
--//. cost of comparing a numeric column with a numeric constant = a
--//这部分我认为相对难一些.因为查询条件可能不止一个.可能and也可能是or .而且比较也有先后次序.
--//复杂的是谓词可能与select存在一些关联.
--//我仅仅简单分析:
--//重新分析表t,取消前面hack的设置.
scott@test01p> 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
explain plan set statement_id='a1' for select 1 from t where a1=100;
explain plan set statement_id='a2' for select 1 from t where a2=100;
explain plan set statement_id='a3' for select 1 from t where a3=100;
explain plan set statement_id='ax' for select 1 from t where a1=:n1;
explain plan set statement_id='ax' for select 1 from t where a2=:n1;
explain plan set statement_id='ax' for select 1 from t where a3=:n1;
--//注:select部分没有查询字段,这样可以先排除select中涉及字段查询的cpu cost的干扰。
scott@test01p> 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
ax table access full 3 58486 3 1
ax table access full 3 60486 3 1
ax table access full 3 62486 3 1
6 rows selected.
--//注意使用绑定变量与不使用绑定变量cpu_cost差距很大.
--//select部分:
7121.44 * blocks + 150*rows + 20*rows* ( highest_column_id - lowest_column_id)
= 7121.44 * 4 + 150*100 = 43485.76 = 43486
--//可以发现where中cost对比如下:
--//使用非绑定变量的情况:
a1=100 48486-43486 = 5000
a2=100 50486-43486 = 7000
a3=100 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*(column_id-1)*20).
--//实际上可以理解每次比较的cpu cost是50.
--//补充实际上字段成本在select部分计算(看后面的例子就明白了).我这里仅仅推导出每次比较的cpu cost是50.
--//使用绑定变量的情况:
--//细节不在说了,可以推导出每次比较的cpu cost是150.为什么使用绑定变量比非绑定变量这么多?不理解.
--//先放弃分析绑定变量的情况...
--//看看多个条件的情况呢.
column statement_id format a10
column options format a10
explain plan set statement_id='a12' for select 1 from t where a1=100 and a2=100;
explain plan set statement_id='a21' for select 1 from t where a2=100 and a1=100;
explain plan set statement_id='a23' for select 1 from t where a2=100 and a3=100;
explain plan set statement_id='a13' for select 1 from t where a1=100 and a3=100;
explain plan set statement_id='a123' for select 1 from t where a1=100 and a2=100 and a3=100;
scott@test01p> 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
---------- ------------ ------- ---- -------- ------- ----
a12 table access full 3 50536 3 1
a21 table access full 3 50536 3 1
a23 table access full 3 52536 3 1
a13 table access full 3 52536 3 1
a123 table access full 3 52536 3 1
--//statement_id=a12的情况, 50536-43486 = 7050
--//我的理解:where a1=100 and a2=100. 因为要取a2字段
--//rows*(highest_column_id - 1)*20 = 100*20 = 2000.
--//(7050-2000)/50 = 101, 说明比较101次.
--//可以这样理解 a1=100比较100次,仅仅1条记录过滤出来,这样a2=100仅仅需要比较1次.总共101次.
--//补充我认为正常情况下应该比较选择性好的字段先比较,这样减少后续比较的次数.
--//statement_id=a123的情况, 52536-43486 = 9050
--//因为要取a3字段
--//rows*(highest_column_id - 1)*20 = 100*2*20 = 4000.
--//(9050-4000)/50 = 101,说明比较101次.我的理解应该是101.01次(102?),小数点后面的忽略了。
--//where部分cost, 比较成本.每次比较cost=50,实际上情况可能更复杂,
--//当我查询select 1 from t... ,select部分没有查询字段.
--//如果查询 explain plan set statement_id='bb' for select a3 from t where a2=100 ;呢?
--//前面的select部分已经查询a3字段.看看情况如何?我在这里迷糊一段时间.....
scott@test01p> explain plan set statement_id='bb' for select a3 from t where a2=100 ;
explained.
scott@test01p> 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部分,开始仅仅需要取到a1字段(即使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以及查询条件结合起来判断,出现的情况可能比较复杂.
--//补充or的测试:
scott@test01p> explain plan set statement_id='cc' for select a3 from t where a1=100 or a2= 100;
explained.
scott@test01p> select statement_id,operation, options, cost, cpu_cost, io_cost, time from plan_table where statement_id='cc';
statement_ operation options cost cpu_cost io_cost time
---------- ---------------- ------- ---- -------- ------- ----
cc select statement 3 55476 3 1
cc table access full 3 55476 3 1
--//select部分,开始仅仅需要取到a2字段(即使select部分包含a3):
7121.44 * blocks + 150*rows + 20*rows* (highest_column_id - lowest_column_id)
7121.44 * 4 + 150*100 + 20*100* ( 2 - 1) = 45485.76 = = 45486
--//where部分:
比较100+99次 ,199*50 = 9950
--//注我开始认为200次.这里应该考虑重合部分.你可以这么理解假设a1=100已经符合条件,a2=100就不需要比较了.
仅仅1条符合a1=100.1条符合a2=100.共计2条(这里不知道是否考虑重合部分,估计太小也忽略了)。取a3字段成本 :
20*rows* (highest_column_id - lowest_column_id)
20*1*(3-2)*2=40
--//cpu cost
45486 + 9950 + 40 = 55476
--//完全符合.
7.最后看看谓词条件存在函数的情况.
column statement_id format a10
column options format a10
explain plan set statement_id='a1' for select 1 from t where to_char(a1)='100';
explain plan set statement_id='a2' for select 1 from t where to_char(a2)='100';
explain plan set statement_id='a3' for select 1 from t where to_char(a3)='100';
explain plan set statement_id='a3' for select 1 from t where to_char(a3)=:c1;
select statement_id,operation, options, cost, cpu_cost, io_cost, time from plan_table where options='full';
scott@test01p> 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
a3 table access full 3 62486 3 1
--//select部分:
7121.44 * blocks + 150*rows + 20*rows* ( highest_column_id - 1)
= 7121.44 * 4 + 150*100 = 43485.76 = 43486
--//可以发现where中cost对比如下:
to_char(a1)='100' 58486-43486 = 15000
to_char(a2)='100' 60486-43486 = 17000
to_char(a3)='100' 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.
8.总结:
--//cup cost的计算是 每块7121.44,每行150,字段看位置(n-1)*20(注仅仅取最考后的字段计算),比较50以及次数,函数100.
--//使用绑定变量比较成本150,不知道为什么这样.这个我不再探究.
--//许多情况很复杂,最后做一个例子验证看看.
scott@test01p> explain plan set statement_id='x1' for select to_char(a1),to_char(a2),to_char(a3) from t where to_char(a2)='100';
explained.
scott@test01p> select statement_id,operation, options, cost, cpu_cost, io_cost, time from plan_table where statement_id='x1';
statement_ operation options cost cpu_cost io_cost time
---------- ---------------- ------- ---- -------- ------- ----
x1 select statement 3 60506 3 1
x1 table access full 3 60506 3 1
--//select部分,查询到a2
7121.44 * blocks + 150*rows + 20*rows* ( highest_column_id - 1)
=7121.44 * 4 + 150*100 +20*100*1 = 45485.76 = 45486
--//注意3个函数to_char.注仅仅1条返回.好像这部分oracle没有考虑.
100*rows*3
=1*100*3 = 300
--//where部分:
--//比较100次, 函数占100,比较占50
100*(100+50) = 15000
--//字段成本,仅仅1条返回,也就是取a3字段仅仅1次.注意前面select部分已经查询到a2字段,这样lowest_column_id=2
20*rows* ( highest_column_id - lowest_column_id)
= 20*1*(3-2) = 20
--//累计:
45486 + 15000+ 20 = 60506
scott@test01p> explain plan set statement_id='x2' for select a1,a2,a3 from t where to_char(a2)='100';
explained.
scott@test01p> select statement_id,operation, options, cost, cpu_cost, io_cost, time from plan_table where statement_id='x2';
statement_ operation options cost cpu_cost io_cost time
---------- ---------------- ------- ---- -------- ------- ----
x2 select statement 3 60506 3 1
x2 table access full 3 60506 3 1
--//可以看出select部分包含函数,cpu cost不计算的.最后回到前面别人问的问题:
--//http://blog.itpub.net/267265/viewspace-2653964/
scott@test01p> explain plan for select /*+ index_ffs(t1) */ count(*) from t1 where val > 100;
explained.
scott@test01p> select cpu_cost from plan_table;
cpu_cost
--------
72914400
72914400
--//select部分,查询到val
7121.44 * blocks + 150*rows + 20*rows* ( highest_column_id - 1)
7121.44* 10000 + 150*10000 + 20*10000* ( 2- 1) = 72914400
--//已经吻合.
--//为什么没有比较的cpu cost消耗,我的理解这是由索引的特性决定的块间有序,块内无序.通过行目录排序键值,这样扫描叶子时比较
--//的次数是有限的。
--//显然oracle忽略了索引叶子块中的比较测试。
--//在看看索引的情况:
scott@test01p> explain plan set statement_id='x1' for select * from dept where deptno=10;
explained.
scott@test01p> select statement_id,operation, options, cost, cpu_cost, io_cost, time from plan_table where statement_id='x1';
statement_ operation options cost cpu_cost io_cost time
---------- ---------------- -------------- ---- -------- ------- ----
x1 select statement 1 8361 1 1
x1 table access by index rowid 1 8361 1 1
x1 index unique scan 0 1050 0 1
--//select部分:
7121.44*1+1*150+20*1*(3-1) = 7311.44
8361-1050 = 7311
--//select部分是吻合的.
--//where部分(索引部分)呢?也就是unique scan 的cpu cost 1050如何确定的呢?
scott@test01p> explain plan set statement_id='x2' for select 1 from dept where deptno=10;
explained.
scott@test01p> select statement_id,operation, options, cost, cpu_cost, io_cost, time from plan_table where statement_id='x2';
statement_ operation options cost cpu_cost io_cost time
---------- ---------------- ----------- ---- -------- ------- ----
x2 select statement 0 1050 0 1
x2 index unique scan 0 1050 0 1
scott@test01p> create index i_dept_dname on dept(dname);
index created.
scott@test01p> explain plan set statement_id='x3' for select * from dept where dname='accounting';
explained.
scott@test01p> column options format a30
scott@test01p> select statement_id,operation, options, cost, cpu_cost, io_cost, time from plan_table where statement_id='x3';
statement_ operation options cost cpu_cost io_cost time
---------- ---------------- ---------------------- ---- -------- ------- ----
x3 select statement 2 14633 2 1
x3 table access by index rowid batched 2 14633 2 1
x3 index range scan 1 7321 1 1
--//range scan 访问块按 7121.44计算.
--//7321-7121 = 200,每行150,比较1次 50 .猜测不知道是否正确?
--//这样反推 unique scan block的cpu cost = 1050 - 200 = 850.
--//绑定变量的情况为什么比较150.不理解? 感觉有点高.是否绑定变量有一个替换的过程.
column statement_id format a10
column options format a10
explain plan set statement_id='a12' for select 1 from t where a1=100 and a2=100;
explain plan set statement_id='x12' for select 1 from t where a1=100 and a2=:n2;
explain plan set statement_id='x21' for select 1 from t where a1=:n1 and a2=100;
explain plan set statement_id='y12' for select 1 from t where a1=:n1 and a2=:n2;
explain plan set statement_id='z123' for select 1 from t where a1=:n1 and a2=:n2 and a3=:n3;
scott@test01p> 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
---------- ------------ ------- ---- -------- ------- ----
a12 table access full 3 50536 3 1
x12 table access full 3 50636 3 1
x21 table access full 3 50636 3 1
y12 table access full 3 60636 3 1
z123 table access full 3 62637 3 1
--//x12, select部分:
7121.44 * blocks + 150*rows + 20*rows* ( highest_column_id - lowest_column_id)
7121.44*4 + 150*100 = 43485.76 = 43486
--//where:
--//比较100+1
100*50 = 5000
1*150 = 150
--//字段成本:
20*rows* ( highest_column_id - lowest_column_id)
20*100*(2-1) = 2000
--//43486+5000+150+2000 = 50636 ,ok!!
--//y12 ,select部分:
7121.44 * blocks + 150*rows + 20*rows* ( highest_column_id - lowest_column_id)
7121.44*4 + 150*100 = 43485.76 = 43486
--//where:
--//比较100+1,2个都是绑定变量
101*150 = 15150
--//字段成本:
20*rows* ( highest_column_id - lowest_column_id)
20*100*(2-1) = 2000
--//43486+15150+2000 = 60636,ok!!
--//z123, select部分:
7121.44 * blocks + 150*rows + 20*rows* ( highest_column_id - lowest_column_id)
7121.44*4 + 150*100 = 43485.76 = 43486
--//where:
--//比较100+1+0.01
101*150 = 15150
101.01*150 = 15151.50
--//字段成本:
20*rows* ( highest_column_id - lowest_column_id)
20*100*(3-1) = 4000
--//43486+15150+4000 = 62636. 差1.我估计如果101.01*150 = 15151.50计算基本符合..
--//43485.76+15151.50+4000 = 62637.26
--//又有点专牛角尖了.这些细节不重要.不过看到计算结果与测试一致,还是蛮有成就感的.
上一篇: MySQL建表查询