精華區beta Database 關於我們 聯絡資訊
※ 引述《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)