全局索引两种SQL查询执行计划疑惑。 本帖最后由 kay5804 于 2010-08-26 17:22:55 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 SQL> select count(*) from tbl_mo_part_01 partition(MO_01) where orgaddr='8615000000000'; COUNT(*)---------- 26Elapsed: 00:00:00.01Execution Plan----------------------------------------------------------Plan hash value: 2243574388----------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |----------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 15 | 3 (0)| 00:00:01 || 1 | SORT AGGREGATE | | 1 | 15 | | ||* 2 | INDEX RANGE SCAN| MO_INX_PT_01 | 13 | 195 | 3 (0)| 00:00:01 |----------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 2 - access("ORGADDR"='8615000000000') filter(TBL$OR$IDX$PART$NUM("TBL_MO_PART_01",0,1,0,ROWID)=1)Statistics---------------------------------------------------------- 0 recursive calls 0 db block gets 3 consistent gets 0 physical reads 0 redo size 530 bytes sent via SQL*Net to client 524 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed[/code]问题: 1、 为什么两个执行计划不一样。 2、 两个SQL执行为什么不走partition 。 3、 为什么第一个SQL语句分区字段没有索引,会出现TABLE ACCESS BY GLOBAL INDEX ROWID 4、 第二个SQL语句为什么指定了分区不走分区partition range 1. 查询语句都完全不一样!2. part_index字段上要建索引,才会使用分区过滤!3. 也正迷惑中4. 同2 3、orgaddr上面有全局索引 1.猜测全局索引中包含了分区字段的信息,所以直接通过索引求出count(*)了。2.走分区未必比走索引快,你可以用大数据量少返回值的查询来验证一下执行计划是否跟现在的不同。3.同14.事实上我自己测试的例子中走的是partition range single,然后执行的是table access full,反而没走索引,所以这个应该是跟数据和数据分布以及返回值多少有关系。 问题1:SQL1是先获取匹配的ROWID列表,然后根据ROWID列表读表中part_index的值是否为0,而SQL2则是先获取ROWID列表,然后根据ROWID直接判断该ROWID是否在指定分区中,很显然SQL2比SQL1高效,因为它不需要读表的数据问题2:因为索引不是局部索引。你可以暂时把索引的数据看作是一张表,你的索引表没有分区,当前不会走partition问题3:索引的依赖于orgaddr列,与part_index无关问题4:因为通过TBL$OR$IDX$PART$NUM函数可以直接判断指定的ROWID是否属于指定的分区,所以也没有partition range,原因同问题2 不同意LS所说第二种写法更高效,事实上两种的效率几乎没有差别,因为part_index=0 就可以限定在指定分区进行记录查找,执行计划没有这样走是因为有更高效的实现方式,不论数据量多少,两种写法差别不大。 part_index=0 ,因为part_index的数据不在索引中,那么如果不读表的数据,那么怎么知道它的值是0?从执行计划上看,它并没有如LS所说乖乖地使用限定分区的方法,没有出现partition关键字。 并不一定要有索引才能根据分区字段值来找分区,一个简单的问题,一个表有10个分区,分区字段是日期,那么select count(*) from tab where yyyymmdd >= 20100831; 20100831是它的一个分区,你说这个语句会走分区扫描还是全表扫描? 求高手指点...急 帮忙看看这两段程序有什么不同? 我的oracle9i启动不起来了。救命啊,在线等~~~!!! 求一SQL语句 初学oracle,有个挺简单的存储过程(书上的例子),麻烦朋友们帮忙给说道说道,谢谢!!! oracle9.2.0.1升级为9.2.07时无法出现"universal installer" 升级界面??? 在线急求sql 一个简单的存储过程调用问题,请各位赐教 成批插入问题 如何创建一个跨两个表空间的触发器? 数据库导出问题 求大神赐教 ,和sys下面Package bodies 有关。 启动oracle数据库时出错 如何同时监听2个节点上的oracle实例
----------
26Elapsed: 00:00:00.01Execution Plan
----------------------------------------------------------
Plan hash value: 2243574388----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 15 | 3 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 15 | | |
|* 2 | INDEX RANGE SCAN| MO_INX_PT_01 | 13 | 195 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------- 2 - access("ORGADDR"='8615000000000')
filter(TBL$OR$IDX$PART$NUM("TBL_MO_PART_01",0,1,0,ROWID)=1)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
530 bytes sent via SQL*Net to client
524 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed[/code]问题: 1、 为什么两个执行计划不一样。
2、 两个SQL执行为什么不走partition 。
3、 为什么第一个SQL语句分区字段没有索引,会出现TABLE ACCESS BY GLOBAL INDEX ROWID
4、 第二个SQL语句为什么指定了分区不走分区partition range
2. part_index字段上要建索引,才会使用分区过滤!
3. 也正迷惑中
4. 同2
2.走分区未必比走索引快,你可以用大数据量少返回值的查询来验证一下执行计划是否跟现在的不同。
3.同1
4.事实上我自己测试的例子中走的是partition range single,然后执行的是table access full,反而没走索引,所以这个应该是跟数据和数据分布以及返回值多少有关系。
问题2:因为索引不是局部索引。你可以暂时把索引的数据看作是一张表,你的索引表没有分区,当前不会走partition
问题3:索引的依赖于orgaddr列,与part_index无关
问题4:因为通过TBL$OR$IDX$PART$NUM函数可以直接判断指定的ROWID是否属于指定的分区,所以也没有partition range,原因同问题2
从执行计划上看,它并没有如LS所说乖乖地使用限定分区的方法,没有出现partition关键字。
那么select count(*) from tab where yyyymmdd >= 20100831; 20100831是它的一个分区,你说这个语句会走分区扫描还是全表扫描?