การเข้าร่วมได้รับการปรับให้เหมาะสมกับส่วนคำสั่งที่ runtime หรือไม่


14

เมื่อฉันเขียนแบบสอบถามเช่นนี้ ...

select *
from table1 t1
join table2 t2
on t1.id = t2.id

เครื่องมือเพิ่มประสิทธิภาพ SQL ไม่แน่ใจว่าเป็นคำที่ถูกต้องแปลว่าเป็น ...

select *
from table1 t1, table2 t2
where t1.id = t2.id

โดยพื้นฐานแล้วคำสั่งเข้าร่วมใน SQL Server เป็นวิธีที่ง่ายกว่าในการเขียน sql หรือไม่ หรือใช้จริงในเวลาทำงาน?

แก้ไข: ฉันเกือบจะตลอดและจะใช้เข้าร่วมไวยากรณ์ ฉันแค่อยากรู้ว่าเกิดอะไรขึ้น


1
คุณช่วยอธิบายเกี่ยวกับ "เกือบ" ได้ไหม? คุณจะใช้ไวยากรณ์แบบเก่าเมื่อใดและเพราะเหตุใด
Aaron Bertrand

2
กรณีขอบหนึ่งที่ทำให้เกิดความแตกต่างคือถ้าคุณเพิ่ม (คัดค้าน) GROUP BY ALLใน
Martin Smith

@MartinSmith มีใครใช้โดยGROUP BY ALLมีจุดประสงค์หรือไม่ :-)
Aaron Bertrand

@AaronBertrand - ฉันสงสัยมัน! อย่าคิดว่าฉันเคยเห็นใครใช้มัน
Martin Smith

คำตอบ:


20

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

นี่คือบทพิสูจน์โดยใช้ AdventureWorks ที่ไม่มีCROSS JOINและfilterเกิดขึ้น


การเข้าร่วมที่ชัดเจน:

ป้อนคำอธิบายรูปภาพที่นี่


การเข้าร่วมโดยนัย:

ป้อนคำอธิบายรูปภาพที่นี่


ดูสิ! แผนการที่เหมือนกันผลลัพธ์ที่เหมือนกันไม่มีการรวมข้ามหรือการกรองใด ๆ

(เพื่อความชัดเจนคำเตือนของSELECTโอเปอเรเตอร์ในทั้งสองกรณีนี้คือการแปลงโดยนัยที่มีผลกระทบต่อ cardinality ไม่มีส่วนเกี่ยวข้องกับการเข้าร่วมในทั้งสองกรณี)


20

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

-- Input tree (ISO-89)
SELECT
    p.Name,
    Total = SUM(inv.Quantity)
FROM 
    Production.Product AS p,
    Production.ProductInventory AS inv
WHERE
    inv.ProductID = p.ProductID
GROUP BY
    p.Name
OPTION (RECOMPILE, QUERYTRACEON 8605, QUERYTRACEON 3604);

แผนผังอินพุต ISO-89

-- Input tree (ISO-92)
SELECT
    p.Name,
    Total = SUM(inv.Quantity)
FROM Production.Product AS p
JOIN Production.ProductInventory AS inv ON
    inv.ProductID = p.ProductID
GROUP BY
    p.Name
OPTION (RECOMPILE, QUERYTRACEON 8605, QUERYTRACEON 3604);

แผนผังอินพุต ISO-92

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

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


4

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


4

ตกลงฉันอยากรู้อยากเห็นดังนั้นฉันจึงทำการทดสอบ ฉันได้รับแผนการปฏิบัติจริงสำหรับสิ่งต่อไปนี้

select * 
from sys.database_principals prin, sys.database_permissions perm
WHERE prin.principal_id = perm.grantee_principal_id

และ

select * 
from sys.database_principals prin
JOIN sys.database_permissions perm
    ON prin.principal_id = perm.grantee_principal_id

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

ดังที่กล่าวไว้คุณควรใช้JOINไวยากรณ์เพราะง่ายต่อการอ่านและคุณมีโอกาสน้อยที่จะทำผิดพลาดโดยเฉพาะอย่างยิ่งในการค้นหาที่ซับซ้อน และไวยากรณ์*=/ =*สำหรับการOUTERรวมได้ถูกลบไปแล้วตั้งแต่ SQL-Server 2005

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