Dextrys DBA's space
10.2版本CBO计算中的基数问题
查看( 192 ) /
评论( 11 )
TAG:
-
棉花糖ONE发布于2008-03-28 15:49:07
-
不至于吧,要是按照作者的脚本做测试,得到的结果应该和书上的类似
-
anlinew
发布于2008-03-28 15:57:51
-
一回事,可能oracle为了更易懂吧
-
litterbaby发布于2008-03-28 16:05:07
-
其实LEWIS在书上就说了就是一回事
-
kelsoncong
发布于2008-03-28 16:22:40
-
书上有一个数据类型的例子,
分别用了date,int和char类型的字段表示日期,
然后分别用这三个字段做条件进行筛选,
最后证明用date类型的得到的基数最小,因此证明用日期类型表示日期最好,
但是在10.2的数据库上所得到的rows的值全部一样,都等于实际筛选出来的记录条数,
因此row和card应该不是一个东西
PS:LEWIS写书的时候,oracle 最高版本是10.1.0.4
-
suniori
发布于2008-03-28 16:24:41
-
我觉得CARD 和ROW 是一回事,名字不一样而已,你也可以叫他COUNT
-
kelsoncong
发布于2008-03-28 16:30:00
-
SQL>
SQL> select *
2 from t1
3 where d1 between to_date('30-12-2002','dd-mm-yyyy')
4 and to_date('05-01-2003','dd-mm-yyyy')
5 ;
已选择7行。
执行计划
----------------------------------------------------------
Plan hash value: 3617692013
----------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
----------------------------------------------------------
| 0 | SELECT STATEMENT | | 7 | 196 | 3 |
|* 1 | TABLE ACCESS FULL| T1 | 7 | 196 | 3 |
----------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("D1">=TO_DATE('2002-12-30 00:00:00', 'yyyy-mm-dd
hh24:mi:ss') AND "D1"<=TO_DATE('2003-01-05 00:00:00', 'yyyy-mm-dd
hh24:mi:ss'))
Note
-----
- cpu costing is off (consider enabling it)
- dynamic sampling used for this statement
统计信息
----------------------------------------------------------
169 recursive calls
0 db block gets
52 consistent gets
2 physical reads
0 redo size
725 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
4 sorts (memory)
0 sorts (disk)
7 rows processed
SQL> select *
2 from t1
3 where n1 between 20021230 and 20030105
4 ;
已选择7行。
执行计划
----------------------------------------------------------
Plan hash value: 3617692013
----------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
----------------------------------------------------------
| 0 | SELECT STATEMENT | | 7 | 196 | 3 |
|* 1 | TABLE ACCESS FULL| T1 | 7 | 196 | 3 |
----------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("N1">=20021230 AND "N1"<=20030105)
Note
-----
- cpu costing is off (consider enabling it)
- dynamic sampling used for this statement
统计信息
----------------------------------------------------------
5 recursive calls
0 db block gets
34 consistent gets
0 physical reads
0 redo size
725 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
7 rows processed
SQL> select *
2 from t1
3 where v1 between '20021230' and '20030105'
4 ;
已选择7行。
执行计划
----------------------------------------------------------
Plan hash value: 3617692013
----------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
----------------------------------------------------------
| 0 | SELECT STATEMENT | | 7 | 196 | 3 |
|* 1 | TABLE ACCESS FULL| T1 | 7 | 196 | 3 |
----------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("V1">='20021230' AND "V1"<='20030105')
Note
-----
- cpu costing is off (consider enabling it)
- dynamic sampling used for this statement
统计信息
----------------------------------------------------------
5 recursive calls
0 db block gets
34 consistent gets
0 physical reads
0 redo size
725 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
7 rows processed
SQL> spool out
-
kelsoncong
发布于2008-03-28 16:31:37
-
看看这个例子,所有的rows的值都是7,都等于实际取得的值rows processed
按照CBO书的介绍,这三种写法的card值应该不一样的
-
棉花糖ONE发布于2008-03-28 17:02:15
-
这问题可能是10.2处理掉了吧,你把optimizer_features_enable改成'9.2.0'看看结果
-
ihekoko
发布于2008-03-28 18:22:56
-
楼主
你说的这一章 作者主要是想证明采用合适的数据类型可以防止oracle选择奇怪的执行计划
你所建立的表的数据很可能和作者测试用的表有很大的区别
比如 某个表中存储的是一年的相关数据 每个月的数据都很平均
对于日期类型的 d1 between to_date('01-01-2007','dd-mm-yyyy') and to_ate('01-02-2007','dd-mm-yyyy')
oracle 很容易的就知道这里的Card(rows)大概会是 numrows/12(一年中的一个月)
但是 数字类型的 n1 between 20070101 and 20070201 ( (20070201-20070101)/(max_value-min_value))
或者字符类型的 v1 between '20070101' and '20070201' (('20070201'-'20070101')/(max_value-min_value))
oracle 很有可能就得到一个“错误”的Card(rows)
于是采用了一个我们看起来奇怪的执行计划
这里所谓的错误 只是oracle根据它自己的算法算出的card(rows)并不是我们想的那样
-
kelsoncong
发布于2008-03-31 09:01:12
-
多谢几位的建议,我用的例子就是书上提供的,环境也完全一样的,
我按照棉花糖的指示调整了一下
optimizer_features_enable
发现结果和书上的就几乎一样了,
看来oracle 10.2对优化器这一块做了不小的调整,修正了很多问题,使的基数值更加的准确,几乎和实际的值相同
(这可能也是oracle把card修改成row的原因吧)
-
kelsoncong
发布于2008-03-31 09:01:37
-
再次感谢几位的帮助!
