พิจารณาตารางต่อไปนี้
ทดสอบ
SQL> desc test;
Name Null? Type
----------------------------------------- -------- ----------------------------
NUM NOT NULL NUMBER
NUM2 NUMBER(10)
NUM3 NUMBER
NUM NUM2 NUM3
---------- ---------- ----------
1 1 1
2 2 2
ทดสอบ2
SQL> desc test2;
Name Null? Type
----------------------------------------- -------- ----------------------------
NUM NOT NULL NUMBER
NUM2 NOT NULL NUMBER
NUM3 NUMBER
NUM NUM2 NUM3
---------- ---------- ----------
1 1 1
3 1 1
ตามหนังสือหากมีการแทนที่เงื่อนไข NOT IN เป็น LEFT Outer join; ประสิทธิภาพการค้นหาจะเพิ่มขึ้น
อธิบายแผน 1
SQL> select *
from test
where num NOT IN (select num
from test2);
NUM NUM2 NUM3
--- --------- ----------
2 2 2
แผนปฏิบัติการ
----------------------------------------------------------
Plan hash value: 856752680
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 | 5 (0)| 00:00:01 |
|* 1 | FILTER | | | | | |
| 2 | TABLE ACCESS FULL| TEST | 2 | 4 | 3 (0)| 00:00:01 |
|* 3 | TABLE ACCESS FULL| TEST2 | 2 | 26 | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter( NOT EXISTS (SELECT /*+ */ 0 FROM "TEST2" "TEST2" WHERE
LNNVL("NUM"<>:B1)))
3 - filter(LNNVL("NUM"<>:B1))
ดังนั้นฉันจึงสร้างดัชนีบนคอลัมน์ num ของทั้งสองตารางและเขียนแบบสอบถามใหม่เป็น:
อธิบายแผน2
SQL> select *
from test
left join test2 on (test.num = test2.num)
where test2.num is null;
NUM NUM2 NUM3 NUM NUM2 NUM3
---------- ---------- ---------- ---------- ---------- ----------
2 2 2
Execution Plan
----------------------------------------------------------
Plan hash value: 1525288557
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Tim
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 82 | 4 (0)| 00:
|* 1 | FILTER | | | | |
| 2 | NESTED LOOPS OUTER | | 2 | 82 | 4 (0)| 00:
| 3 | TABLE ACCESS FULL | TEST | 2 | 4 | 3 (0)| 00:
| 4 | TABLE ACCESS BY INDEX ROWID| TEST2 | 1 | 39 | 1 (0)| 00:
|* 5 | INDEX RANGE SCAN | ID2 | 1 | | 0 (0)| 00:
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("TEST2"."NUM" IS NULL)
5 - access("TEST"."NUM"="TEST2"."NUM"(+))
เห็นได้ชัดว่าฉันขาดอะไรบางอย่างไปเนื่องจากวิธีการที่แนะนำนั้นมีราคาแพงกว่า นี่เป็นเพราะการกระจายข้อมูลของฉันหรือไม่
เวอร์ชัน: Oracle 10g
select test.*
แทนselect *
แล้วดูว่ามีความแตกต่างหรือไม่ - person APC   schedule 28.05.2011