Inner เข้าร่วม vs ที่ไหน


257

มีความแตกต่างในประสิทธิภาพ (ใน oracle) ระหว่าง

Select * from Table1 T1 
Inner Join Table2 T2 On T1.ID = T2.ID

และ

Select * from Table1 T1, Table2 T2 
Where T1.ID = T2.ID

?


1
เพียงเพื่อบันทึกฉันได้เห็นการค้นหาส่งกลับผลลัพธ์ที่แตกต่างกันโดยการเปลี่ยนจากการเข้าร่วมเป็นข้อที่
BlackTigerX

12
@BlackTigerX: ผลลัพธ์ที่แตกต่างกันอย่างไร มีผู้ร่วมภายนอกที่เกี่ยวข้องหรือไม่ เนื่องจากฉันไม่เห็นว่าผลลัพธ์จะแตกต่างกันอย่างไรระหว่างinner join ... onเกณฑ์การเข้าร่วมที่เทียบเคียงกันในwhereข้อ
แชนนอนชดเชย

ในฐานข้อมูล oracle รุ่นเก่าไม่มีอยู่จริงjoin
MajidTaheri

2
@MajidTaheri: คุณอายุเท่าไหร่ที่พูดถึง Oracle? ออราเคิลรองรับเวอร์ชันใดก็ได้ที่รองรับเครื่องหมาย JOIN
Jonathan Leffler

มองหาคำตอบทั่วไปหรือแนวทางปฏิบัติที่ดีที่สุดโดยพิจารณาจากกรณีเล็ก ๆ น้อย ๆ ต้องการดู "การจับคู่ซ้ำ" ที่มีความซับซ้อนมากขึ้นซึ่งมีคำสั่งที่เกี่ยวข้องกับเงื่อนไข AND หลายรายการ อย่างน้อยกับ SQL Server มีจุดไขว้
crokusek

คำตอบ:


195

No! แผนการดำเนินการเดียวกันดูที่สองตารางเหล่านี้:

CREATE TABLE table1 (
  id INT,
  name VARCHAR(20)
);

CREATE TABLE table2 (
  id INT,
  name VARCHAR(20)
);

แผนการดำเนินการของแบบสอบถามโดยใช้การรวม Inner:

-- with inner join

EXPLAIN PLAN FOR
SELECT * FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.id;

SELECT *
FROM TABLE (DBMS_XPLAN.DISPLAY);

-- 0 select statement
-- 1 hash join (access("T1"."ID"="T2"."ID"))
-- 2 table access full table1
-- 3 table access full table2

และแผนการดำเนินการสำหรับแบบสอบถามโดยใช้ส่วนคำสั่ง WHERE

-- with where clause

EXPLAIN PLAN FOR
SELECT * FROM table1 t1, table2 t2
WHERE t1.id = t2.id;

SELECT *
FROM TABLE (DBMS_XPLAN.DISPLAY);

-- 0 select statement
-- 1 hash join (access("T1"."ID"="T2"."ID"))
-- 2 table access full table1
-- 3 table access full table2

4
ฉันอยากจะดูว่ามีเอกสารอย่างเป็นทางการจาก Oracle ที่พูดเกี่ยวกับเรื่องนี้หรือไม่
4 Cover Cover

68

หากเครื่องมือเพิ่มประสิทธิภาพคิวรีทำงานได้ถูกต้องไม่ควรมีข้อแตกต่างระหว่างคิวรีเหล่านั้น พวกเขาเป็นเพียงสองวิธีในการระบุผลลัพธ์ที่ต้องการเหมือนกัน


22
ใช่การแสดงควรจะเหมือนกัน แต่ SELECT * FROM Table1, Table2 WHERE ... ไวยากรณ์คือความชั่วร้าย!
Joel Coehoorn

2
ฉันพบว่ามันง่ายกว่าที่จะเข้าใจ INNER JOINS มากกว่าไวยากรณ์ SQL-92 ไมล์สะสมของคุณอาจแตกต่างกันไป
Craig Trader

25
ฉันพบว่า WHERE ไวยากรณ์อ่านง่ายกว่า INION JION - ฉันคิดว่ามันคล้ายกับ Vegemite คนส่วนใหญ่ในโลกอาจพบว่ามันน่าขยะแขยง แต่เด็ก ๆ นำมากินมันรักมัน
ScottCher

3
Vegemite นั้นน่ารังเกียจจริง ๆ แต่จากนั้นฉันก็รักการขูด ไปคิด
StingyJack

2
@Darryl ฉันคิดว่าJOINมันง่ายกว่าที่จะอ่านเพราะเงื่อนไขในการเข้าร่วมตารางถูกกำหนดไว้ที่นั่นทันทีแทนที่จะเป็น "ที่ไหนสักแห่ง" ในWHEREข้อ ฉันชอบที่จะจองWHEREข้อสำหรับการ จำกัด ชุดข้อมูล (เช่นWHERE DATE > (SYSDATE - 1)) แทนที่จะกำหนดว่าตารางมีความสัมพันธ์กันอย่างไร (เช่นWHERE T1.ID = T2.ID) สำหรับตารางเล็ก ๆ เช่นตัวอย่างที่เป็นปัญหานั้นมีความแตกต่างกันเล็กน้อย แต่สำหรับคิวรีขนาดใหญ่ที่เกี่ยวข้องกับหลาย ๆ ตารางและเงื่อนไขต่าง ๆ ฉันคิดว่ามันทำให้เข้าใจง่าย
ImaginaryHuman072889

61

พวกเขาควรจะเหมือนกัน อย่างไรก็ตามในฐานะที่เป็นแบบฝึกหัดการเข้ารหัสฉันอยากจะเห็นการเข้าร่วม มันชัดเจนถึงเจตนาของคุณ


8
ฉันเห็นด้วย. โดยเฉพาะอย่างยิ่งถ้าคุณกำลังเข้าร่วมหลายตารางมันง่ายกว่ามากในการแยกคำสั่งเลือกถ้าคุณกำลังเข้าร่วมที่ชัดเจน
Paul Morie

13
จริง Joins เป็นตัวแทนของความสัมพันธ์ทางความหมายระหว่างชุดข้อมูลสองชุด แต่เป็นตำแหน่งที่แนะนำชุดกรอง +1
EightyOne Unite

26

การใช้JOINทำให้โค้ดอ่านง่ายขึ้นเนื่องจากอธิบายได้ด้วยตนเอง

ไม่มีความแตกต่างของความเร็ว ( ฉันเพิ่งทดสอบ ) และแผนการดำเนินการเหมือนกัน


ขอบคุณ. ฉันกำลังมองหาการบีบอัดความเร็วระหว่างสองวิธีนี้
Farhad Navayazdan

14

ฉันไม่รู้เกี่ยวกับ Oracle แต่ฉันรู้ว่ามีการยกเลิกไวยากรณ์เก่าใน SQL Server และจะหายไปในที่สุด ก่อนที่ฉันจะใช้ไวยากรณ์เก่านั้นในแบบสอบถามใหม่ฉันจะตรวจสอบสิ่งที่ Oracle วางแผนจะทำกับมัน

ฉันชอบไวยากรณ์ที่ใหม่กว่าแทนที่จะผสมผสานเกณฑ์การเข้าร่วมกับเงื่อนไขอื่นที่จำเป็น ในไวยากรณ์ที่ใหม่กว่านั้นจะมีความชัดเจนมากขึ้นว่าอะไรที่จะสร้างการเข้าร่วมและเงื่อนไขอื่น ๆ ที่ถูกนำไปใช้ ไม่ใช่ปัญหาใหญ่ในแบบสอบถามสั้น ๆ เช่นนี้ แต่มันจะสับสนมากขึ้นเมื่อคุณมีคิวรีที่ซับซ้อนมากขึ้น เนื่องจากผู้คนเรียนรู้เกี่ยวกับการสืบค้นพื้นฐานฉันจึงมีแนวโน้มที่จะต้องการให้คนเรียนรู้ที่จะใช้ไวยากรณ์การเข้าร่วมก่อนที่พวกเขาต้องการในการสืบค้นที่ซับซ้อน

และอีกครั้งฉันไม่ทราบว่า Oracle เจาะจง แต่ฉันรู้ว่า SQL Server รุ่นเก่าที่เหลืออยู่รวมถึงข้อบกพร่องแม้ใน SQL Server 2000 และให้ผลลัพธ์ที่ไม่สอดคล้องกัน ใช้ หวังว่า Oracle จะไม่ประสบปัญหาเดียวกัน แต่แน่นอนว่าการรวมซ้ายและขวาอาจทำให้ยากที่จะแสดงในไวยากรณ์เก่า

นอกจากนี้ยังเป็นประสบการณ์ของฉัน (และแน่นอนว่านี่เป็นความเห็นส่วนตัวคุณอาจมีประสบการณ์ที่แตกต่างกันไป) ผู้พัฒนาที่ใช้มาตรฐานการเข้าร่วม ANSII มักจะมีความเข้าใจที่ดีขึ้นเกี่ยวกับการเข้าร่วมคืออะไรและมันหมายถึงอะไร ข้อมูลจากฐานข้อมูล ฉันเชื่อว่าเป็นเพราะคนส่วนใหญ่ที่มีความเข้าใจฐานข้อมูลที่ดีมักจะเขียนข้อความค้นหาที่ซับซ้อนมากขึ้นและคนเหล่านั้นดูเหมือนจะง่ายต่อการดูแลรักษาโดยใช้มาตรฐาน ANSII มากกว่าแบบเก่า


1
สาธุน้องชาย ลงกับเพื่อนร่วมทีม !!
ScottCher

14

[สำหรับคะแนนโบนัส ... ]

การใช้ไวยากรณ์ JOIN ช่วยให้คุณสามารถคอมเม้นท์การรวมได้ง่ายขึ้นเมื่อรวมทั้งหมดไว้ในหนึ่งบรรทัด นี้สามารถเป็นประโยชน์ถ้าคุณกำลังดีบักแบบสอบถามที่ซับซ้อน

อย่างที่คนอื่น ๆ พูดว่าพวกมันใช้งานได้เหมือนกันอย่างไรก็ตามการเข้าร่วมนั้นชัดเจนยิ่งขึ้นจากคำแถลงเจตนา ดังนั้นจึงอาจช่วยให้เครื่องมือเพิ่มประสิทธิภาพการสืบค้นทั้งในรุ่น oracle ปัจจุบันในบางกรณี (ฉันไม่รู้ว่ามันทำ) มันอาจช่วยให้เครื่องมือเพิ่มประสิทธิภาพการสืบค้นใน Oracle รุ่นอนาคต (ไม่มีใครมีความคิดใด ๆ ) หรืออาจช่วยได้ คุณเปลี่ยนผู้จำหน่ายฐานข้อมูล


2
หรือ ... เปลี่ยน INNER JOINS เป็น LEFT JOINS ได้ง่ายๆดังนั้นคุณจะเห็นว่าการเข้าร่วมใดทำให้คุณพลาดแถวที่คาดไว้ ฉันทำเช่นนี้เพราะฉันทำแบบสอบถามทั้งหมดในครั้งเดียว หากคุณแสดงความคิดเห็นภายในเข้าร่วมคุณต้องทำกระบวนการกำจัด มันใช้เวลานาน แต่ +1 สำหรับคุณเพราะนี่คือหนึ่งในเหตุผลที่ฉันชอบสำหรับการเข้าร่วมภายในนอกเหนือจากการอ่าน!
Matthew McPeak

13

พวกมันเหมือนกันในเชิงตรรกะ แต่ใน Oracle เวอร์ชันก่อนหน้านี้ที่ใช้ไวยากรณ์ ANSI มักจะมีข้อบกพร่องในกรณีที่ซับซ้อนกว่าดังนั้นบางครั้งคุณอาจพบกับการต่อต้านจากนักพัฒนา Oracle เมื่อใช้งาน


Oracle เวอร์ชั่นก่อนหน้านี้มีข้อบกพร่องในเรื่องนี้หรือไม่? เร็วแค่ไหน รุ่นใด
ScottCher

Metalink มีรายละเอียด ... พวกมันปรากฏขึ้นทุกที่
David Aldridge

7

ประสิทธิภาพควรเหมือนกัน แต่ฉันขอแนะนำให้ใช้รุ่นเข้าร่วมเนื่องจากความชัดเจนที่เพิ่มขึ้นเมื่อพูดถึงการรวมภายนอก

นอกจากนี้ผลิตภัณฑ์คาร์ทีเซียนที่ไม่ได้ตั้งใจยังสามารถหลีกเลี่ยงได้โดยใช้รุ่นสำหรับการเข้าร่วม

เอฟเฟ็กต์ที่สามนั้นง่ายกว่าในการอ่าน SQL ด้วย WHERE-condition ที่ง่ายขึ้น


ฉันคิดว่ากุญแจเป็นผลที่ไม่ได้ตั้งใจซึ่งเป็นเกณฑ์ที่ไม่ชัดเจน หากคุณระบุประเภทของการเข้าร่วมที่คุณรู้ว่าสิ่งที่คุณได้รับ ฉันได้พบว่าฐานข้อมูลที่แตกต่างกันและแม้แต่เวอร์ชั่นที่แตกต่างกันของแพลตฟอร์มฐานข้อมูลเดียวกันจะจัดการกับค่า Null ที่แตกต่างกันในการเข้าร่วมโดยนัย เมื่อคุณระบุด้านซ้าย / ขวาด้านใน / ด้านนอกคุณใช้เวลาคิดว่าอะไรถูกต้อง เมื่อคุณใช้วิธีการที่คลุมเครือคุณจะคิดว่ามันใช้งานได้ตามที่คุณต้องการ / ตั้งใจ
Steve Kallestad

6

อย่าลืมว่าใน Oracle หากแอตทริบิวต์คีย์การเข้าร่วมนั้นมีชื่อเหมือนกันในทั้งสองตารางคุณสามารถเขียนเป็น:

select *
from Table1 inner join Table2 using (ID);

นอกจากนี้ยังมีแผนแบบสอบถามเหมือนกันแน่นอน


ฉัน rollbacked ฉบับแก้ไขเพราะก่อนหน้านี้มีการเปลี่ยนแปลงความหมายของคำตอบ

5

ในสถานการณ์ที่ตารางอยู่ในรูปแบบปกติที่ 3 การรวมระหว่างตารางไม่ควรเปลี่ยนแปลง เช่นเข้าร่วมลูกค้าและการชำระเงินควรจะยังคงเหมือนเดิม

อย่างไรก็ตามเราควรแยกแยะร่วมจากฟิลเตอร์ การเข้าร่วมเป็นเรื่องเกี่ยวกับความสัมพันธ์และตัวกรองเกี่ยวกับการแบ่งส่วนทั้งหมด

ผู้เขียนบางคนอ้างถึงมาตรฐาน (เช่น Jim Melton; Alan R. Simon (1993) การทำความเข้าใจกับ SQL ใหม่: คู่มือฉบับสมบูรณ์ Morgan Kaufmann. pp 11–12. ไอ 978-1-55860-245-8) เขียนเกี่ยวกับประโยชน์ที่จะนำมาใช้ร่วมกับไวยากรณ์มากกว่าตารางที่คั่นด้วยเครื่องหมายจุลภาคในส่วนคำสั่ง

ฉันเห็นด้วยกับมุมมองนี้โดยสิ้นเชิง

มีหลายวิธีในการเขียน SQL และบรรลุผลลัพธ์เดียวกัน แต่สำหรับหลาย ๆ คนที่ทำงานเป็นทีมความชัดเจนของซอร์สโค้ดนั้นเป็นสิ่งสำคัญและแน่นอนว่าการแยกตารางเกี่ยวข้องกันจากตัวกรองที่เฉพาะเจาะจงหรือไม่ รหัส.


Inner join on หมายถึง cross cross ที่ไหน เครื่องหมายจุลภาคข้ามการเข้าร่วมที่มีลำดับความสำคัญต่ำกว่าการรวมคำหลัก เมื่อเทียบกับ "ตัวกรอง" ไม่เกี่ยวข้องกับการเข้าร่วมภายใน NFs ไม่เกี่ยวข้องกับการสอบถาม ไม่มีสิ่งใดในมาตรฐานที่ส่งเสริมการใช้คำหลักร่วมกับเครื่องหมายจุลภาค การปรับให้เหมาะที่สุดเล็กน้อยจัดการกับ & ที่เหมือนกัน คำตอบนี้เป็นความเข้าใจที่คลาดเคลื่อน
philipxy

1) ฉันเดา @philipxy พยายามที่จะพูดว่า "ในส่วนคำสั่ง FROM ที่คั่นด้วยเครื่องหมายจุลภาคมีความหมายเหมือนกับตารางที่ CROSS เข้าร่วม" ฉันเห็นด้วยกับที่ แน่นอนคุณสามารถติดกับไวยากรณ์เก่าและที่สามารถอยู่ร่วมกับอนุประโยคเข้าร่วม เครื่องมือเพิ่มประสิทธิภาพ RDBMS จะเข้าใจทั้งสองกรณีอย่างสมบูรณ์เหมือนกัน (ในกรณีที่เทียบเท่าแน่นอน) และจะอธิบายรายละเอียดของแผนเดียวกัน
abrittaf

4

ใน PostgreSQL ไม่มีความแตกต่างแน่นอน - พวกเขาทั้งสองถือเอาแผนแบบสอบถามเดียวกัน ฉันแน่ใจว่า 99% เป็นกรณีของ Oracle



2

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


1

มันเป็นความจริงที่เป็นไปตามหน้าที่แบบสอบถามทั้งสองควรถูกประมวลผลในลักษณะเดียวกัน อย่างไรก็ตามประสบการณ์ได้แสดงให้เห็นว่าหากคุณเลือกจากมุมมองที่ใช้ไวยากรณ์การเข้าร่วมใหม่เป็นสิ่งสำคัญในการจัดโครงสร้างคิวรีของคุณโดยใช้ เครื่องมือเพิ่มประสิทธิภาพของ Oracle อาจสับสนถ้ามุมมองใช้คำสั่ง "เข้าร่วม" แต่แบบสอบถามที่เข้าถึงมุมมองนั้นใช้วิธีการดั้งเดิมของการเข้าร่วมในส่วนคำสั่ง "ที่ไหน"


นั่นเป็นปัญหาของมุมมองมากกว่าที่จะเข้าร่วมเลย
ไม่อยู่

0

แม้ว่าตัวตนของแบบสอบถามสองรายการอาจจะเห็นได้ชัดว่าบางครั้งก็มีสิ่งแปลก ๆ เกิดขึ้น ฉันได้รับการตอบคำถามที่มีแผนการดำเนินการที่แตกต่างกันเมื่อย้ายเข้าร่วมเพรดิเคตจากที่ใดก็ได้ใน Oracle 10g (สำหรับตำแหน่งที่ดีกว่าแผน) แต่ฉันไม่สามารถทำซ้ำปัญหานี้ในตารางที่เรียบง่ายและข้อมูล ฉันคิดว่ามันขึ้นอยู่กับข้อมูลและสถิติของฉัน เครื่องมือเพิ่มประสิทธิภาพเป็นโมดูลที่ค่อนข้างซับซ้อนและบางครั้งก็ทำงานได้อย่างน่าอัศจรรย์

นั่นเป็นเหตุผลที่เราไม่สามารถตอบคำถามนี้โดยทั่วไปเพราะมันขึ้นอยู่กับฐานข้อมูลภายใน แต่เราควรจะรู้ว่าคำตอบจะต้องมี ' ไม่มีความแตกต่าง '


0

ฉันมีปริศนานี้ในวันนี้เมื่อตรวจสอบหนึ่ง sp ของเราหมดเวลาในการผลิตเปลี่ยนการเข้าร่วมภายในบนโต๊ะที่สร้างขึ้นจากฟีด xml เป็น 'ที่ไหน' ประโยคแทน .... เวลา exec เฉลี่ยตอนนี้ 80ms กว่า 1,000 การประหารชีวิตในขณะที่ ก่อนผู้บริหารเฉลี่ยคือ 2.2 วินาที ... ความแตกต่างที่สำคัญในแผนการดำเนินการคือการหายไปของการค้นหาคีย์ ... ข้อความที่คุณไม่รู้จนกว่าคุณจะทดสอบโดยใช้ทั้งสองวิธี

ไชโย



0

อย่างที่ kiewik กล่าวว่าแผนปฏิบัติการเหมือนกัน

คำสั่ง JOIN นั้นง่ายต่อการอ่านเท่านั้นทำให้ง่ายขึ้นที่จะไม่ลืมเงื่อนไข ON และรับผลิตภัณฑ์คาร์ทีเซียน ข้อผิดพลาดเหล่านี้อาจตรวจจับได้ยากในการสืบค้นแบบยาวโดยใช้การรวมหลายประเภท: SELECT * จาก t1, t2 WHERE t1.id = t2.some_field

หากคุณลืมเงื่อนไขการเข้าร่วมเพียงครั้งเดียวคุณจะได้รับแบบสอบถามที่ส่งคืนระเบียนจำนวนมากเกินไป ... นานเกินไป กวีบางคนใช้ DISTINCT เพื่อแก้ไขแบบสอบถาม แต่ก็ยังคงนานมากที่จะดำเนินการ

นั่นเป็นเหตุผลว่าทำไมการใช้คำสั่ง JOIN จึงเป็นวิธีปฏิบัติที่ดีที่สุดนั่นคือการบำรุงรักษาที่ดีขึ้นและความสามารถในการอ่านที่ดีขึ้น

ยิ่งไปกว่านั้นถ้าฉันจำได้ดี JOIN ได้รับการปรับให้เหมาะสมที่สุดเกี่ยวกับการใช้หน่วยความจำ


0

ฉันมีคำตอบที่ดีเพิ่มเติม :

นั่นคือสิ่งที่ถูกกำหนดเป็น SQL92 และ SQL89 ตามลำดับไม่มีความแตกต่างระหว่างประสิทธิภาพแม้ว่าคุณสามารถละเว้นคำว่า INNER (โดยใช้เพียงแค่ JOIN ชัดเจนพอและในแบบสอบถามที่ง่ายที่สุดที่คุณบันทึก 5 ครั้งของแป้นพิมพ์ในขณะนี้ คน)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.