ใช้คำหลักเข้าร่วมหรือไม่


45

แบบสอบถาม SQL ต่อไปนี้เหมือนกัน:

SELECT column1, column2
FROM table1, table2
WHERE table1.id = table2.id;

SELECT column1, column2
FROM table1 JOIN table2 
ON table1.id = table2.id;

และแน่นอนส่งผลให้มีแผนแบบสอบถามเดียวกันในทุก DBMS ที่ฉันเคยลอง

แต่บ่อยครั้งที่ฉันอ่านหรือฟังความคิดเห็นที่หนึ่งดีกว่าอีกแน่นอน ตามธรรมชาติแล้วคำกล่าวอ้างเหล่านี้จะไม่ได้รับการยืนยัน

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

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


1
ทำไมไม่โพรไฟล์มันและให้พวกเราที่เหลือรู้ผล? โดยทั่วไปประสิทธิภาพการทำงานนั้นสูงกว่าความพึงพอใจของสไตล์มาก
Demian Brecht

3
"ผลลัพธ์ในแผนการสืบค้นที่เหมือนกันในทุก DBMS ที่ฉันเคยลอง" ถ้านี่อาจมีคำตอบในแง่ของประสิทธิภาพก็จะถามใน stackoverflow.com อนิจจาพวกเขาเป็นคำถามเดียวกัน
SingleNegationElimination

อ้า .. พลาดไปเลย :)
Demian Brecht

2
"อัตนัย" ไม่ได้หมายถึง "ความคิดเห็นของคุณ" ฉันได้แก้ไขนี้ชนิดของการตามเกณฑ์ที่กำหนดไว้ในคำถามที่พบบ่อย
Aaronaught

ฉันยังมีแนวโน้มที่จะลดความประหลาดใจที่ฉันคิดว่าคุณเพิ่งตอบคำถามของคุณเอง ความประหลาดใจไม่ดี
ปีเตอร์ B

คำตอบ:


60

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

ตัวอย่างเช่นใช้แบบสอบถามต่อไปนี้:

select *
from table1, table2, table3, table4
where table1.id = table2.id
and table2.id = table3.id
and table3.id = table4.id
and table1.column1 = 'Value 1'

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

อย่างไรก็ตามตอนนี้รับรหัสนี้:

select *
from table1 join table2 on table1.id = table2.id
join table3 on table2.id = table3.id
join table4 on table3.id = table4.id
where table1.column1 = 'Value 1'

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


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

5
+1 สำหรับ "การแยกข้อกังวล" เข้าร่วมนำข้อมูลเข้าด้วยกันโดยที่ส่วนคำสั่งกำหนดชุดย่อยของข้อมูลที่คุณสนใจ

39

ไวยากรณ์ join เข้ามาแทนที่ syna syntax เก่าในปี 1992 ปัจจุบันไม่มีเหตุผลที่จะเขียนโค้ดด้วย syna syntax คุณไม่ได้อะไรเลยและคุณต้องเจอกับปัญหาบางอย่างที่คุณไม่มีกับไวยากรณ์ที่ชัดเจน

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

หากคุณตั้งใจจะเข้าร่วมข้ามไวยากรณ์เข้าร่วมอย่างชัดเจนจะทำให้ชัดเจนในขณะที่อยู่ในไวยากรณ์โดยนัยคนทำบำรุงรักษาอาจคิดว่าคุณลืมที่จะเพิ่มข้อที่ไหน

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

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

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


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

8

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

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

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

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


2
อย่างไรก็ตามคุณเข้าใจผิดเอกสารเหล่านั้นเล็กน้อย ประการแรกมีสามเกณฑ์จริง ๆ หนึ่งยิง GEQO เมื่อคุณชี้ให้เห็น; อีกสอง (จากและเข้าร่วมข้อ จำกัด การล่มสลาย) ท้ายทำให้ไม้ติดเพื่อเลือกดัชนีที่ใช้งานได้มากกว่าการจัดระเบียบคำสั่งเข้าร่วมอีกครั้ง ประการที่สองและที่สำคัญเช่นกันแบบสอบถามจะถูกเขียนใหม่เมื่อมีการแยกวิเคราะห์ สิ่งนี้ส่งผลให้แบบสอบถามตัวอย่างแรกถูกแยกวิเคราะห์ลงในแผนผังคิวรีที่เหมือนกันกับของคิวรีที่สอง - ขีด จำกัด จากนั้นแจ้งให้ PG ทราบว่าควรลองเรียงลำดับการรวมใหม่หรือไม่
Denis de Bernardy

8

ทีนี้นี่คือมุมมองทฤษฎีเซตของมัน:

เมื่อคุณใช้เครื่องหมายจุลภาคเพื่อคั่นชื่อตารางสองอัน (หรือมากกว่า) สิ่งที่คุณต้องการคือผลิตภัณฑ์คาร์ทีเซียน ทุกแถวของตาราง 'ซ้าย' จะถูก 'จับคู่' (ตัดแบ่ง) กับตารางด้านขวา

ตอนนี้ถ้าคุณเขียนบางอย่างในส่วนคำสั่งที่ไหนมันเหมือนกับการวางเงื่อนไขลงใน 'การต่อข้อมูล' ที่บอกแถวที่ 'เชื่อมโยง' กับแถวใด

นี่คือ "การเข้าร่วม" แถว :) และด้วยเหตุนี้คำสำคัญการเข้าร่วมที่ช่วยให้ไวยากรณ์อ่านง่ายขึ้นและเข้าใจได้ง่ายขึ้นว่าคุณ 'ต้องการ' เข้าร่วมในค่าทั่วไปบางอย่าง คล้ายกับสิ่งที่ @Dustin ได้ชี้แจงไว้ข้างต้น

ตอนนี้ DBMS ทุกตัวนั้นฉลาดเช่นกันมันไม่ได้คำนวณผลิตภัณฑ์คาร์ทีเซียนก่อนแล้วจึงกรองข้อมูล (สิ้นเปลืองอย่างมาก) แต่จะขึ้นอยู่กับโครงสร้างคิวรี สิ่งเดียวที่ฉันคิดได้ก็คือเมื่อคุณขอให้ 'เข้าร่วม' มันเหมือนกับการทำให้กิจกรรมการเข้าร่วมชัดเจนและอาจช่วยให้เรียกใช้รหัสได้เร็วขึ้น (เท่าไหร่คุณจะต้องทำโปรไฟล์และดู) แต่ใน กรณีที่คั่นด้วยเครื่องหมายจุลภาคต้องใช้เวลาในการคิดกลยุทธ์ที่เหมาะสม ฉันอาจจะผิด แต่ฉันแค่คาดเดาการศึกษาเป็นวิธีที่จะรหัสมัน ...


5

ฉันคิดว่าโดยทั่วไปแล้วจะใช้งบ JOIN ได้ดีกว่าสำหรับกรณีนั้น

หากในอนาคตสถานการณ์เกิดขึ้นที่ต้องเปลี่ยนคำสั่งจาก INNER JOIN เป็น OUTER JOIN สิ่งนี้จะง่ายกว่ามากในการทำคำสั่งที่สอง


3

RDBMS ใด ๆ จะทำให้พวกเขาเป็นสิ่งเดียวกันในแง่ของการดำเนินการ มันลงมาว่าจะอ่านและแสดงออกได้มากกว่านี้หรือไม่

ใช้การเข้าร่วมเพื่อให้ชัดเจนว่าการจับคู่เข้าร่วมคืออะไรและการเลือกที่แท้จริงคืออะไรใน:

select name, deptname
from people p, departments d
where p.deptid = d.id and p.is_temp = 'Y'

เมื่อเทียบกับ

select name, deptname
from people p
    inner join departments d on p.deptid = d.id
where p.is_temp = 'Y'

กรณีหลังทำให้ชัดเจนทันทีซึ่งเป็นเงื่อนไขการเข้าร่วมและซึ่งเป็นเกณฑ์การคัดเลือก


1

ฉันเคยเห็นผลลัพธ์ทั้งสองครั้งในชุดการปรับแต่งที่แตกต่างกันและหากหน่วยความจำทำหน้าที่เป็นแบบ ms-sql2k จากแบบสอบถามที่มีขนดกจริงๆ ในตัวอย่างหนึ่งนั้นรูปแบบเก่าที่ใช้กับ * = ส่งผลให้เกิดประสิทธิภาพที่เร็วขึ้นประมาณ 4x ไม่มีใครรวมถึงพวกนักเทคนิคของไมโครซอฟท์ของเราสามารถอธิบายได้ว่าทำไม พวก MS ติดป้ายว่ามันผิด ฉันไม่เคยเห็นมันอีกเลย

เนื่องจาก RDBMS ส่วนใหญ่ฉลาดพอที่จะไม่ทำแบบเต็ม Cartesians เหตุผลที่ใหญ่ที่สุดที่ฉันคิดว่าจะไม่ใช้ (นอกเหนือจากที่คิดค่าเสื่อมราคา) คือคนส่วนใหญ่อายุต่ำกว่า 30-35 ปีที่ฉันเคยทำงานด้วยไม่เคยเห็น รูปแบบเก่ามาก่อนและหลงทางอย่างหนักเมื่อพวกเขาพบมัน


แน่นอนว่าการเข้าร่วมทางด้านซ้ายนั้นไม่เคยให้ผลลัพธ์ที่ถูกต้องอย่างน่าเชื่อถือ (ดู BOL สำหรับ SQL Server 2000) ดังนั้นแม้ว่ามันจะเร็วกว่าฉันก็จะเข้ามาแทนที่มัน
HLGEM

ฉันไม่เคยพบสิ่งนั้นและการค้นหาด้วยเครื่องหมายดอกจันไม่สิ้นสุดคุณมีตัวอย่างหรือไม่
Bill

-1

เลิกใช้รูปแบบเก่าแล้วคุณไม่ควรใช้

ไม่ควรมีข้อโต้แย้งว่าสิ่งใดดีกว่าหรือไม่ รหัสใหม่ไม่ควรใช้ไวยากรณ์เก่า


ฉันคิดว่าคำตอบนี้ไม่ได้เพิ่มอะไรเลยโดยไม่บอกว่าทำไมจึงเลิกใช้แล้วและไม่ควรใช้
RemcoGerlich

1
@RemcoGerlich ว่าทำไมเลิกใช้แล้วไม่ได้อยู่ในการสนทนาที่นี่ สิ่งที่อยู่ภายใต้การสนทนาที่นี่คือการใช้ไวยากรณ์เก่าหรือใหม่ ไม่ว่าอย่างใดอย่างหนึ่งจะดีกว่าอื่น ๆ หรือไม่เป็น moot: คุณไม่ควรใช้ไวยากรณ์เก่า ทำไมคำถามการอภิปรายอีก (หนึ่งที่ถูกตัดสินเมื่อ 20 ปีที่แล้ว)
Pieter B

-4

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


Downvoters: มีอะไรที่ไม่ถูกต้องตามความเป็นจริงในการตอบกลับนี้หรือว่าเป็นเพียง "ไม่พอใจกับคุณ" downvotes?
Adam Libuša
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.