作者noguest (guest)
看板Database
标题Re: [SQL ] 最近遇到的一个问题,请求解答
时间Wed Mar 28 12:54:41 2007
※ 引述《qrtt1 (愚人)》之铭言:
: 如果你只用到 B.xxx
: 就没有必要把 A, B 都拿来做卡氏积
: select A.*, B_partial.xxx
: from A, (select B.xxx, B.id from B) B_partial
: WHERE B_partial.id = A.id;
: 单纯取用 B.xxx 与 B.id 就可以了
这是比较属於学术上的说法, 在实作上, 绝大部份的情况, 这两种
写法对 database 来说是一样的. 以 Oracle 为例:
SQL> explain plan for select a.*, b.id2
from test a, test2 b
where a.id1=b.id1;
SQL> explain plan for select a.*, b_partial.id2
from test a, (select id1, id2 from test2) b_partial
where a.id1=b_partial.id1;
这两种写法的 execution plan 是完全相同, 如下:
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10M| 661M| 932 (19)| 00:00:12 |
|* 1 | HASH JOIN | | 10M| 661M| 932 (19)| 00:00:12 |
| 2 | TABLE ACCESS FULL| TEST | 12010 | 457K| 9 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| TEST2 | 1067K| 26M| 777 (4)| 00:00:10 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."ID1"="B"."ID1")
简单地说, 第二个写法虽然用了 b_partial, 但最後产生的 plan 还是在处理A和B,
和第一个写法相同, 并非照着字面上的文句来处理. 这就像是 view 一样, 对
database 来说是透明的. 在这个例子, 如果先把 b_partial 定义成一个 view,
产生出来的 plan 仍是不变.
会照成这个情形的原因很简单, 那就是 database 实际上并不会真的产生卡氏积
或是类似卡氏积的东西, 反而只是以类似 pointer 的形式, 记录 A 的第m个row
及 B 的第n个row 符合 where 的条件, 再把结果存到 cursor 中. 换句话说,
最後 select 的 column 如何组合并不会影响 execution plan, 而是在 where
中用到的 column 会影响到.
在少数的情况下, 这两种写法的执行速度会有差别, 但差别的地方不在 plan, 也和
卡氏积无关. 会有差别的主要原因严格上要算是个 bug 或是 future enhancement,
算是特例的情况.
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 64.9.239.175
※ 编辑: noguest 来自: 64.9.239.175 (03/28 13:12)