การเพิ่มประสิทธิภาพแบบสอบถามไม่ได้อยู่ในการรวมภายนอกด้านซ้าย

พิจารณาตารางต่อไปนี้

ทดสอบ

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


person Ricko M    schedule 28.05.2011    source แหล่งที่มา
comment
คุณได้โพสต์ข้อมูลแล้ว แต่ไม่ใช่ข้อมูลตาราง เนื่องจากความแตกต่าง ฉันจึงมีแนวโน้มที่จะเชื่อว่าคอลัมน์ที่ถูกเปรียบเทียบนั้นเป็นโมฆะ เนื่องจากข้อมูลในบทความนี้   -  person OMG Ponies    schedule 28.05.2011
comment
Oracle 10g อัปเดตที่เป็นปัญหาเช่นกัน :)   -  person Ricko M    schedule 28.05.2011
comment
แบบสอบถามทั้งสองของคุณส่งคืนชุดผลลัพธ์ที่แตกต่างกัน เวอร์ชันที่สองยังส่งคืนข้อมูลจากตารางที่สองด้วย ฉันคาดหวังว่าแบบสอบถามที่ส่งคืนข้อมูลจากสองตารางจะมีราคาแพงกว่าแบบสอบถามที่ส่งคืนข้อมูลจากตารางเดียว ลองใช้คำค้นหาที่สองด้วย select test.* แทน select * แล้วดูว่ามีความแตกต่างหรือไม่   -  person APC    schedule 28.05.2011
comment
@APC ใช่แล้ว! นั่นคือเหตุผล คุณช่วยโพสต์เป็นคำตอบให้ฉันยอมรับได้ไหม ไชโย!   -  person Ricko M    schedule 28.05.2011


คำตอบ (1)


แบบสอบถามทั้งสองของคุณส่งคืนชุดผลลัพธ์ที่แตกต่างกัน เวอร์ชันที่สองยังส่งคืนข้อมูลจากตารางที่สองด้วย ฉันคาดหวังว่าแบบสอบถามที่ส่งคืนข้อมูลจากสองตารางจะมีราคาแพงกว่าแบบสอบถามที่ส่งคืนข้อมูลจากตารางเดียว

ลองใช้คำค้นหาที่สองด้วย select test.* แทน select * แล้วดูว่ามีความแตกต่างหรือไม่

person APC    schedule 28.05.2011