ข้อใดดีกว่า: หลายเงื่อนไขเข้าร่วมหรือหลายเงื่อนไข


13

ฉันพยายามที่จะเปรียบเทียบคำถามที่สอง:

แบบสอบถาม 1:

SELECT a,b,c,d,e
FROM tableA
LEFT JOIN tableB
ON tableA.a=tableB.a
WHERE tableA.b=tableB.b AND tableA.c=tableB.c  AND tableA.d=tableB.d  AND tableA.e=tableB.e 

แบบสอบถาม 2:

SELECT a,b,c,d,e
FROM tableA
LEFT JOIN tableB
ON tableA.a=tableB.a AND tableA.b=tableB.b AND tableA.c=tableB.c  AND tableA.d=tableB.d  
WHERE tableA.e=tableB.e 

ฉันถูกต้องหรือไม่ที่จะบอกว่าคำค้นหาทั้งสองนี้ให้ผลลัพธ์เหมือนกันหรือไม่

นอกจากนี้ถูกต้องหรือไม่ที่จะบอกว่าแบบสอบถามแรกสร้างตารางที่ใหญ่กว่าเพื่อทำWHEREเงื่อนไขที่ใหญ่กว่า ขณะที่กรณีที่สองเรามีตารางสร้างขนาดเล็กที่เรียบง่ายWHEREที่ใช้แล้ว

สมมติว่าผลลัพธ์เหมือนกันควรเลือกแบบสอบถามใด มีปัญหาเรื่องประสิทธิภาพที่ชัดเจนหรือไม่?


3
ไม่คุณพูดไม่ถูก มันจะเป็นอย่างนั้นถ้าเป็นINNER JOINแต่ด้วยสิ่งLEFT JOINนี้จะให้ผลลัพธ์ที่แตกต่าง โดยทั่วไปเงื่อนไขที่คุณเพิ่มลงในWHEREแบบสอบถามที่สองของคุณจะแปลงJOINเป็นINNER JOIN
Lamak

อาโอเค. ฉันทำตามสิ่งที่คุณพูด หากฉันแก้ไขINNER JOINคำถามเกี่ยวกับประสิทธิภาพยังคงใช้ได้อยู่หรือไม่
Geoff

4
สำหรับการเข้าร่วมภายในไม่ควรมีประสิทธิภาพแตกต่างกัน ที่กล่าวว่าสำหรับการอ่านและการแสดงออกที่เหมาะสมของความตั้งใจที่คุณใช้เกณฑ์ควรจะเข้าร่วมในและเกณฑ์การกรองในON WHERE
Aaron Bertrand

@percube ใช่ฉันพลาดเงื่อนไขนั้นไป
Lamak

คำตอบ:


10

หากเราพิจารณาว่าคุณใช้INNER JOINแทนLEFT JOIN(ซึ่งดูเหมือนจะเป็นเจตนาของคุณ) เคียวรีทั้งสองนี้จะเทียบเท่ากับหน้าที่ ตัวเพิ่มประสิทธิภาพข้อความค้นหาจะตรวจสอบและประเมินเกณฑ์ในWHEREส่วนคำสั่งและส่วนคำสั่งของคุณFROMและพิจารณาปัจจัยเหล่านี้ทั้งหมดเมื่อสร้างแผนแบบสอบถามเพื่อให้บรรลุแผนการดำเนินการที่มีประสิทธิภาพมากที่สุด หากเราทำEXPLAINทั้งสองคำสั่งเราจะได้ผลลัพธ์เดียวกัน:

แบบสอบถาม 1 :

EXPLAIN
SELECT 
  tableA.ColA
  ,tableA.ColB
  ,tableA.ColC
  ,tableA.ColD
  ,tableA.ColE
FROM tableA
  JOIN tableB ON tableA.ColA=tableB.ColA
WHERE 
  tableA.ColB=tableB.ColB 
  AND tableA.ColC=tableB.ColC 
  AND tableA.ColD=tableB.ColD  
  AND tableA.ColE=tableB.ColE

[ผลลัพธ์] :

| ID | SELECT_TYPE |  TABLE | TYPE | POSSIBLE_KEYS |    KEY | KEY_LEN |    REF | ROWS |                          EXTRA |
------------------------------------------------------------------------------------------------------------------------
|  1 |      SIMPLE | tableA |  ALL |        (null) | (null) |  (null) | (null) |    1 |                                |
|  1 |      SIMPLE | tableB |  ALL |        (null) | (null) |  (null) | (null) |    1 | Using where; Using join buffer |

แบบสอบถาม 2 :

EXPLAIN
SELECT 
  tableA.ColA
  ,tableA.ColB
  ,tableA.ColC
  ,tableA.ColD
  ,tableA.ColE
FROM tableA
  JOIN tableB ON tableA.ColA=tableB.ColA
  AND tableA.ColB=tableB.ColB 
  AND tableA.ColC=tableB.ColC 
  AND tableA.ColD=tableB.ColD  
WHERE
  tableA.ColE=tableB.ColE

[ผลลัพธ์] :

| ID | SELECT_TYPE |  TABLE | TYPE | POSSIBLE_KEYS |    KEY | KEY_LEN |    REF | ROWS |                          EXTRA |
------------------------------------------------------------------------------------------------------------------------
|  1 |      SIMPLE | tableA |  ALL |        (null) | (null) |  (null) | (null) |    1 |                                |
|  1 |      SIMPLE | tableB |  ALL |        (null) | (null) |  (null) | (null) |    1 | Using where; Using join buffer |

คุณสามารถตรวจสอบรายละเอียดทั้งหมดได้จากลิงค์ต่อไปนี้ ฉันยังสร้างตัวอย่าง SQL 2008 เพื่อให้คุณสามารถเปรียบเทียบการทำงานของเอ็นจิ้นทั้งสอง (ซึ่งเหมือนกัน):

ตัวอย่างแบบสอบถาม MySQL

ตัวอย่างแบบสอบถาม SQL 2008 (ตรวจสอบให้แน่ใจว่าคุณ 'ดูแผนปฏิบัติการ' สำหรับผลลัพธ์ทั้งสองรายการ)


ขอบคุณสำหรับการแก้ปัญหาอย่างละเอียด ฉันพยายามINNER JOINแทนLEFT JOINและฉันจะได้ผลลัพธ์เดียวกันในสิบของเวลา ฉันคิดว่าฉันรู้ว่าทำไมฉันถึงได้ผลลัพธ์เดียวกัน แต่ทำไมถึงINNER JOINมีประสิทธิภาพที่ดีขึ้น
Geoff

4
เช่นเดียวLEFT JOINกับการรวมภายนอกมันไม่สามารถ จำกัด ชุดข้อมูลที่ด้านกลับเต็มของชุดและจะพยายามดึงแถวทั้งหมดจากตารางนั้น (ในกรณีนี้คือ TableA) หากคุณใช้INNER JOINมันสามารถใช้ประโยชน์จากเกณฑ์นั้นบนทั้งสองตารางและ จำกัด ชุดข้อมูลซึ่งจะให้ผลตอบแทนที่เร็วขึ้น
Mike Fal
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.