不可思议的执行计划

[复制链接]
查看11 | 回复9 | 2007-8-6 15:19:00 | 显示全部楼层 |阅读模式
[PHP]
数据库版本:9.2.0.8.0
--创建测试表
SQL> create table TT

2(
3A NUMBER,
4B NUMBER,
5C NUMBER,
6D NUMBER
7)
8;
Table created.
SQL> create sequence seq_id;
Sequence created.
SQL> begin
2for i in 1..10000 loop
3 insert into tt values(seq_id.nextval,seq_id.nextval,seq_id.nextval,seq_id.nextval);
4 end loop;
5 commit;
6end;
7/
PL/SQL procedure successfully completed.
SQL> create table t as select * from tt;
Table created.
--创建索引
SQL> create index idx_t_a on t(a);
Index created.
SQL> create index idx_tt_c on tt(c);
Index created.
--分析表和索引
SQL> analyze table t compute statistics for table for all columns for all indexes;
Table analyzed.
SQL> analyze table tt compute statistics for table for all indexed columns for all indexes;
Table analyzed.
SQL> set autotrace on;
SQL> select t.*from t,tt
2where t.a=4173 and t.b=tt.b and tt.c=4173;
A
B
C
D
---------- ---------- ---------- ----------
4173 4173 4173 4173

Execution Plan
----------------------------------------------------------
0SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=18)
10 TABLE ACCESS (BY INDEX ROWID) OF \'TT\' (Cost=1 Card=1 Bytes

=6)
21 NESTED LOOPS (Cost=2 Card=1 Bytes=18)--这段是最费解的
32 TABLE ACCESS (BY INDEX ROWID) OF \'T\' (Cost=1 Card=1 By

tes=12)
43 INDEX (RANGE SCAN) OF \'IDX_T_A\' (NON-UNIQUE) (Cost=1
Card=1)
52 INDEX (RANGE SCAN) OF \'IDX_TT_C\' (NON-UNIQUE)

都不知道oracle按照上面的计划执行,怎么也会出来正确的结果,令人费解啊!
Statistics
----------------------------------------------------------

0recursive calls

0db block gets

8consistent gets

0physical reads

0redo size
559bytes sent via SQL*Net to client
503bytes received via SQL*Net from client

2SQL*Net roundtrips to/from client

0sorts (memory)

0sorts (disk)

1rows processed


如果我在t(a,b)建组合索引,在tt(b,c)上建组合索引,执行下列查询,执行计划将会如下:
SQL>select count(*) from t,tt
2
where t.a=4173 and t.b=tt.b and tt.c=4173;
Execution Plan
----------------------------------------------------------
0SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=12)
10 SORT (AGGREGATE)
21 NESTED LOOPS (Cost=2 Card=1 Bytes=12)
32 INDEX (RANGE SCAN) OF \'IDX_T_AB\' (NON-UNIQUE) (Cost=2

Card=1 Bytes=6)
42 INDEX (RANGE SCAN) OF \'IDX_TT_BC\' (NON-UNIQUE)
[/PHP]
回复

使用道具 举报

千问 | 2007-8-6 15:19:00 | 显示全部楼层
正常,没什么费解的吧


回复

使用道具 举报

千问 | 2007-8-6 15:19:00 | 显示全部楼层
IDX_TT_C\'索引是建在TT(c)上的, 这个索引不包括连接字段,那怎么跟上面那个行集作nested loop连接呢???
回复

使用道具 举报

千问 | 2007-8-6 15:19:00 | 显示全部楼层
没明白有什么不可思议的
楼主期待的应该是什么样子的?
回复

使用道具 举报

千问 | 2007-8-6 15:19:00 | 显示全部楼层
oracle 又不知道你选出来的是几条记录罗
如果t 或者 tt 任何一个表选出超过1条的记录,不就要nested loop了么?
回复

使用道具 举报

千问 | 2007-8-6 15:19:00 | 显示全部楼层
作nested loop的两个行集,必须要包含连接列的,如果不包括连接条件,比如实验中的:t.b=tt.b,那它怎么做nested loop了.不知道大家明白我的意思没?
回复

使用道具 举报

千问 | 2007-8-6 15:19:00 | 显示全部楼层
最初由 zhaolinjnu 发布
[B]作nested loop的两个行集,必须要包含连接列的,如果不包括连接条件,比如实验中的:t.b=tt.b,那它怎么做nested loop了.不知道大家明白我的意思没? [/B]

很正常啊。
你认为只有merge join可以出现笛卡儿连接吗?
回复

使用道具 举报

千问 | 2007-8-6 15:19:00 | 显示全部楼层
IDX_TT_C索引是建在TT(c)上的, 这个索引不包括连接字段,那怎么跟上面那个行集作nested loop连接呢???
回复

使用道具 举报

千问 | 2007-8-6 15:19:00 | 显示全部楼层
最初由 zhaolinjnu 发布
[B]IDX_TT_C索引是建在TT(c)上的, 这个索引不包括连接字段,那怎么跟上面那个行集作nested loop连接呢??? [/B]

谁说连接列上有索引才能用NESTED LOOP?

| Id| Operation | Name | Rows| Cost (%CPU)| Time |
--------------------------------------------------------------------
| 0 | SELECT STATEMENT|| 1 |19 (0)| 00:00:01 |
| 1 |SORT AGGREGATE || 1 |
|
|
| 2 | NESTED LOOPS|| 784 |19 (0)| 00:00:01 |
| 3 |TABLE ACCESS FULL| T1 |28 | 2 (0)| 00:00:01 |
| 4 |TABLE ACCESS FULL| T2 |28 | 1 (0)| 00:00:01 |
回复

使用道具 举报

千问 | 2007-8-6 15:19:00 | 显示全部楼层
如果索引上没有连接列,那么至少应该回表找到连接列值,然后才能做nested loop么
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行