我在oracle 11g数据库中有3个表。我再也无法访问跟踪文件或解释计划了。我在日期字段中加入3表,如:
select * from a,b,c where a.date = b.date and b.date = c.date
这需要永远。
当我
select * from a,b,c where a.date = b.date and b.date = c.date and a.date = c.date
它很快。但这应该有所作为吗?
答案 0 :(得分:1)
不确定,但它看起来像一个传递依赖。那就是a.date = b.date and b.date = c.date
然后是a.date = c.date
。您可以修改您的查询,而不是像
select a.*
from a
join b on a.date = b.date
join c on a.date = c.date;
对于所有这3个表,我也会在date
列上有一个索引,因为那是您要加入的列。
答案 1 :(得分:1)
显然,如果连接是A = B,B = C ==>,则数据库不会重写查询。 A = C所以它坚持使用它给出的东西。
请考虑以下事项:
create table a (dt date);
create table b (dt date);
create table c (dt date);
现在填写表格,使a是最小的(5行),b是最大的(100行),c是中间的(50行)。另外,所以b和c中的所有行都不会加入到just中以使事情变得更有趣。
insert into a
select to_date('2015-01-01', 'yyyy-mm-dd') + rownum - 1
from dual
connect by level <= 5
;
insert into b
select to_date('2015-01-01', 'yyyy-mm-dd') + mod(rownum, 10)
from dual
connect by level <= 100
;
insert into c
select to_date('2015-01-01', 'yyyy-mm-dd') + mod(rownum, 10)
from dual
connect by level <= 50
;
我现在要绕过统计数据,完全由数据库决定如何制定计划。
取1:没有从a到c的连接:
explain plan for
select *
from a
, b
, c
where a.dt = b.dt
and b.dt = c.dt
;
这是计划:
select *
from table(dbms_xplan.display())
;
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 250 | 6750 | 9 (0)| 00:00:01 |
|* 1 | HASH JOIN | | 250 | 6750 | 9 (0)| 00:00:01 |
|* 2 | HASH JOIN | | 50 | 900 | 6 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| A | 5 | 45 | 3 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL| B | 100 | 900 | 3 (0)| 00:00:01 |
| 5 | TABLE ACCESS FULL | C | 50 | 450 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("B"."DT"="C"."DT")
2 - access("A"."DT"="B"."DT")
Note
-----
- dynamic statistics used: dynamic sampling (level=2)
首先,由于没有关于表的统计数据,Oracle首先选择对数据进行采样,因此不会盲目进行。在这种情况下,表a首先连接到b,然后结果连接到c。
Take 2:介绍a.dt = c.dt条件:
explain plan for
select *
from a
, b
, c
where a.dt = b.dt
and b.dt = c.dt
and a.dt = c.dt
;
select *
from table(dbms_xplan.display())
;
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 25 | 675 | 9 (0)| 00:00:01 |
|* 1 | HASH JOIN | | 25 | 675 | 9 (0)| 00:00:01 |
|* 2 | HASH JOIN | | 25 | 450 | 6 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| A | 5 | 45 | 3 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL| C | 50 | 450 | 3 (0)| 00:00:01 |
| 5 | TABLE ACCESS FULL | B | 100 | 900 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."DT"="B"."DT" AND "B"."DT"="C"."DT")
2 - access("A"."DT"="C"."DT")
Note
-----
- dynamic statistics used: dynamic sampling (level=2)
你去吧。现在已经切换了连接的顺序,Oracle已经获得了额外的连接路径。 (仅供参考,如果仅使用a.dt = b.dt和a.dt = c.dt,这是相同的计划。)
但是,注意什么?估计不再正确。它最终会猜测25行,而不是250行。因此,额外条件实际上会造成一些混乱。
没有b.dt = c.dt,但是,相同的连接路径,不同的估计(与第一个结果相同的最终结果):
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 250 | 6750 | 9 (0)| 00:00:01 |
|* 1 | HASH JOIN | | 250 | 6750 | 9 (0)| 00:00:01 |
|* 2 | HASH JOIN | | 25 | 450 | 6 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| A | 5 | 45 | 3 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL| C | 50 | 450 | 3 (0)| 00:00:01 |
| 5 | TABLE ACCESS FULL | B | 100 | 900 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."DT"="B"."DT")
2 - access("A"."DT"="C"."DT")
Note
-----
- dynamic statistics used: dynamic sampling (level=2)
长篇故事,因为数据库不会为您假设任何连接路径,在查询中添加一个为数据库提供更多选项,因此可以更改其计划......并且计划中的更改可以肯定会影响结果返回的速度。
答案 2 :(得分:0)
这是您的查询.....
select * from a,b,c where a.date = b.date and .date = c.date and a.date = c.date
现在按照我的观点......
SELECT * FROM a
JOIN B USING(date)
JOIN C USING(date);