全局索引两种SQL查询执行计划疑惑。

jspwind 2010-08-26 05:21:30
-- orgaddr 创建一个全局索引 , part_index 是分区字段 取值为:0~49  50个分区
-- 该表没有主键。part_index 没有建索引

select count(*) from tbl_mo_part_01 where part_index=0 and orgaddr='8615000000000'

COUNT(*)
----------
26

Elapsed: 00:00:00.01

Execution Plan
----------------------------------------------------------
Plan hash value: 463358375

----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 17 | 61 (0)| 00:00:01 | | |
| 1 | SORT AGGREGATE | | 1 | 17 | | | | |
|* 2 | TABLE ACCESS BY GLOBAL INDEX ROWID| TBL_MO_PART_01 | 13 | 221 | 61 (0)| 00:00:01 | 1 | 1 |
|* 3 | INDEX RANGE SCAN | MO_INX_PT_01 | 69 | | 3 (0)| 00:00:01 | | |
----------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - filter("PART_INDEX"=0)
3 - access("ORGADDR"='8615000000000')


Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
28 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


...全文
192 13 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
etsilence 2010-09-02
  • 打赏
  • 举报
回复
并不一定要有索引才能根据分区字段值来找分区,一个简单的问题,一个表有10个分区,分区字段是日期,
那么select count(*) from tab where yyyymmdd >= 20100831; 20100831是它的一个分区,你说这个语句会走分区扫描还是全表扫描?
hyee 2010-08-31
  • 打赏
  • 举报
回复
part_index=0 ,因为part_index的数据不在索引中,那么如果不读表的数据,那么怎么知道它的值是0?
从执行计划上看,它并没有如LS所说乖乖地使用限定分区的方法,没有出现partition关键字。
etsilence 2010-08-30
  • 打赏
  • 举报
回复
不同意LS所说第二种写法更高效,事实上两种的效率几乎没有差别,因为part_index=0 就可以限定在指定分区进行记录查找,执行计划没有这样走是因为有更高效的实现方式,不论数据量多少,两种写法差别不大。
hyee 2010-08-30
  • 打赏
  • 举报
回复
问题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
mahanso 2010-08-30
  • 打赏
  • 举报
回复
还是很迷糊,能太详细点吗?
chogo 2010-08-28
  • 打赏
  • 举报
回复
3、orgaddr上面有全局索引
studentaccp 2010-08-28
  • 打赏
  • 举报
回复
顶起,迷惑等答案中
gelyon 2010-08-28
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 etsilence 的回复:]
1.猜测全局索引中包含了分区字段的信息,所以直接通过索引求出count(*)了。
2.走分区未必比走索引快,你可以用大数据量少返回值的查询来验证一下执行计划是否跟现在的不同。
3.同1
4.事实上我自己测试的例子中走的是partition range single,然后执行的是table access full,反而没走索引,所以这个应该是跟数据和数据分布以及返回值多少有关系。
[/Quote]

犀利哥分析的不错!赞一个
etsilence 2010-08-28
  • 打赏
  • 举报
回复
1.猜测全局索引中包含了分区字段的信息,所以直接通过索引求出count(*)了。
2.走分区未必比走索引快,你可以用大数据量少返回值的查询来验证一下执行计划是否跟现在的不同。
3.同1
4.事实上我自己测试的例子中走的是partition range single,然后执行的是table access full,反而没走索引,所以这个应该是跟数据和数据分布以及返回值多少有关系。
mahanso 2010-08-27
  • 打赏
  • 举报
回复
帮顶一下,我和楼主是同事,我们对这个问题有迷惑,明白的兄弟帮我们解释一下。谢谢。
jspwind 2010-08-27
  • 打赏
  • 举报
回复
高手来分析一下。
碧水幽幽泉 2010-08-26
  • 打赏
  • 举报
回复
1. 查询语句都完全不一样!
2. part_index字段上要建索引,才会使用分区过滤!
3. 也正迷惑中
4. 同2
jspwind 2010-08-26
  • 打赏
  • 举报
回复


SQL> select count(*) from tbl_mo_part_01 partition(MO_01) where orgaddr='8615000000000';

COUNT(*)
----------
26

Elapsed: 00:00:00.01

Execution 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

3,494

社区成员

发帖
与我相关
我的任务
社区描述
Oracle 高级技术相关讨论专区
社区管理员
  • 高级技术社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧