การมี 'OR' ในเงื่อนไข INNER JOIN เป็นความคิดที่ไม่ดีหรือไม่?


96

ในการพยายามปรับปรุงความเร็วของแบบสอบถามที่ช้ามาก (หลายนาทีในสองตารางโดยมีแถวละประมาณ 50,000 แถวเท่านั้นบน SQL Server 2008 ถ้าเป็นเรื่องสำคัญ) ฉันได้ จำกัด ปัญหาให้แคบลงเป็นการรวมORภายในของฉันเช่นใน:

SELECT mt.ID, mt.ParentID, ot.MasterID
  FROM dbo.MainTable AS mt
  INNER JOIN dbo.OtherTable AS ot ON ot.ParentID = mt.ID
                                  OR ot.ID = mt.ParentID

ฉันเปลี่ยนสิ่งนี้เป็น (สิ่งที่ฉันหวังคือ) การรวมด้านซ้ายคู่ที่เทียบเท่าแสดงที่นี่:

SELECT mt.ID, mt.ParentID,
   CASE WHEN ot1.MasterID IS NOT NULL THEN
      ot1.MasterID ELSE
      ot2.MasterID END AS MasterID
  FROM dbo.MainTable AS mt
  LEFT JOIN dbo.OtherTable AS ot1 ON ot1.ParentID = mt.ID
  LEFT JOIN dbo.OtherTable AS ot2 ON ot2.ID = mt.ParentID
  WHERE ot1.MasterID IS NOT NULL OR ot2.MasterID IS NOT NULL

.. และการสืบค้นจะทำงานในเวลาประมาณหนึ่งวินาที!

โดยทั่วไปเป็นความคิดที่ดีที่จะอยู่ORในเงื่อนไขการเข้าร่วมหรือไม่? หรือว่าฉันโชคไม่ดีในการจัดวางตารางของฉัน?


6
แสดงแผนการดำเนินการแทนการสืบค้นของคุณ
Blindy

ดูเหมือนความสัมพันธ์แปลก ๆ
ธานกอนซาเลซ

@Blindy: ความคิดที่ดี ปรากฎว่าแผนการดำเนินการแสดงสิ่งที่ Quassnoi กล่าวถึงด้านล่าง: แบบสอบถามแรกส่งผลให้เกิดการวนซ้ำที่ซ้อนกันในขณะที่รายการที่สองทำด้วยการรวมแฮช
ภาระ

คำตอบ:


115

ประเภทJOINนี้ไม่สามารถปรับให้เหมาะกับ a HASH JOINหรือMERGE JOIN.

สามารถแสดงเป็นการเชื่อมต่อของสองชุดผลลัพธ์:

SELECT  *
FROM    maintable m
JOIN    othertable o
ON      o.parentId = m.id
UNION
SELECT  *
FROM    maintable m
JOIN    othertable o
ON      o.id = m.parentId

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


3
มันสมเหตุสมผลแล้วขอบคุณ ฉันยังไม่แน่ใจว่ามีบางอย่างที่แปลกประหลาดเกี่ยวกับคำถามของฉันหรือว่าฉันควรหลีกเลี่ยงการรวมON w=x OR y=zรูปแบบทั้งหมดหรือไม่
ภาระ

@ladenedge: การรวมเหล่านี้จะดำเนินการโดยใช้การสแกนตารางในลูปที่ซ้อนกัน ซึ่งจะช้าถ้าโต๊ะของคุณมีขนาดใหญ่
Quassnoi

เพื่อให้ชัดเจนเมื่อคุณพูดว่า "การรวมเหล่านี้" คุณหมายถึงการรวมทั้งหมดของแบบฟอร์มON w=x OR y=zหรือไม่ (ขอบคุณสำหรับความอดทนของคุณ!)
ภาระ

3
@ladenedge: อาจมีเงื่อนไขเพิ่มเติมที่สามารถช่วยให้SQL Serverเข้าใจได้ว่าจำเป็นต้องมีการต่อกัน สมมติว่าแบบสอบถามSELECT * FROM othertable WHERE parentId = 1 OR id = 2จะใช้การเชื่อมต่อกันหากทั้งสองช่องถูกจัดทำดัชนีดังนั้นในทางทฤษฎีจึงไม่มีอะไรที่จะขัดขวางการทำสิ่งเดียวกันในการวนซ้ำ ไม่ว่าSQL Serverจะสร้างแผนนี้จริงหรือไม่ขึ้นอยู่กับปัจจัยหลายอย่าง แต่ฉันไม่เคยเห็นมันสร้างขึ้นในชีวิตจริง
Quassnoi

นอกจากนี้โปรดทราบว่าหากคุณรู้ว่าเป็นชุดที่ไม่ปะติดปะต่อกันสหภาพ ALL สามารถปรับปรุงประสิทธิภาพได้อย่างมากโดยหลีกเลี่ยงการรวมชุดผลลัพธ์
Darren Clark

5

ฉันใช้รหัสต่อไปนี้เพื่อให้ได้ผลลัพธ์ที่แตกต่างจากเงื่อนไขที่ได้ผลสำหรับฉัน


Select A.column, B.column
FROM TABLE1 A
INNER JOIN
TABLE2 B
ON A.Id = (case when (your condition) then b.Id else (something) END)

-2

คุณสามารถใช้ UNION ALL แทนได้

SELECT mt.ID, mt.ParentID, ot.MasterID FROM dbo.MainTable AS mt Union ALL SELECT mt.ID, mt.ParentID, ot.MasterID FROM dbo.OtherTable AS ot


UNION ALLจะให้ข้อมูลที่ซ้ำกันเมื่อเทียบJOINกับORเงื่อนไข
CodeMonkey

สำหรับ UNION นั้นจะถูกต้อง สำหรับรายละเอียดเพิ่มเติมโปรดอ่านลิงค์ต่อไปนี้
union-

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