ไม่ควรหลีกเลี่ยงใน


14

ในบรรดานักพัฒนา SQL Server บางคนเป็นความเชื่อที่ถือกันอย่างกว้างขวางว่าNOT INช้ามากและควรเขียนคำสั่งใหม่เพื่อให้ผลลัพธ์เหมือนเดิม แต่ไม่ใช้คำหลัก "ความชั่วร้าย" ( ตัวอย่าง )

มีความจริงใด ๆ หรือไม่?

ตัวอย่างเช่นมีข้อบกพร่องบางอย่างที่รู้จักใน SQL Server (เวอร์ชันใด) ที่ทำให้การสืบค้นที่ใช้NOT INมีแผนการดำเนินการที่เลวร้ายยิ่งกว่าแบบสอบถามที่เทียบเท่าที่ใช้

  • LEFT JOINรวมกับNULLการตรวจสอบหรือ
  • (SELECT COUNT(*) ...) = 0ในWHEREข้อ?

7
บทความนั้นไม่ถูกต้องอย่างมากแม้ว่า "ใน" ไม่ "ต้องเรียกใช้แบบสอบถามเดียวกันซ้ำแล้วซ้ำอีกสำหรับแต่ละแถวใน TableOne" ดูเหมือนว่าผู้โพสต์จะเชื่อว่าIN/ NOT INจะถูกนำมาใช้กับลูปซ้อนกันเสมอ และฉันไม่รู้ว่าstops SQL Server from creating a ‘plan’ควรจะหมายถึงอะไร
Martin Smith

5
@ Heinzi บทความที่คุณเชื่อมโยงไปควรตายในไฟมันเต็มไปด้วยเรื่องไร้สาระ ไลค์ : "เพื่อแทนที่ IN เราใช้ INNER JOIN พวกเขามีประสิทธิภาพในสิ่งเดียวกัน" ปัญหาคือพวกเขาไม่เหมือนกัน ฉันจะไม่ไว้ใจใครบางคนที่ไม่รู้จัก SQL พื้นฐานนั่นคือความแตกต่างระหว่างการเข้าร่วมและการเข้าร่วมกึ่งการวิเคราะห์อะไรเกี่ยวกับพฤติกรรมของ SQL-Server
ypercubeᵀᴹ

คำตอบ:


14

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

DECLARE @Customers TABLE(CustomerID INT);

INSERT @Customers VALUES(1),(2);

DECLARE @Orders TABLE(OrderID INT, CustomerID INT, CompanyID INT);

INSERT @Orders VALUES(10,1,NULL),(11,NULL,5);

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

SELECT [NOT IN] = CustomerID FROM @Customers 
  WHERE CustomerID NOT IN (SELECT CustomerID FROM @Orders);

SELECT [NOT EXISTS] = CustomerID FROM @Customers AS c 
  WHERE NOT EXISTS (SELECT 1 FROM @Orders AS o
  WHERE o.CustomerID = c.CustomerID);

SELECT [EXCEPT] = CustomerID FROM @Customers
EXCEPT SELECT CustomerID FROM @Orders;

ผล:

NOT IN
------
                 -- <-- no results. Is that what you expected?

NOT EXISTS
----------
2

EXCEPT
------
2

ตอนนี้มีปัญหาเรื่องประสิทธิภาพด้วยเช่นกันและฉันก็พูดถึงมัน ในโพสต์บล็อกนี้ ขึ้นอยู่กับข้อมูลและดัชนีNOT EXISTSมักจะมีประสิทธิภาพสูงกว่าNOT INและฉันไม่รู้ว่ามันจะทำงานได้แย่ลงหรือไม่ คุณควรทราบว่าEXCEPTสามารถแนะนำการดำเนินการเรียงลำดับที่แตกต่างกันดังนั้นคุณอาจจบลงด้วยข้อมูลที่แตกต่างกัน (อีกครั้งขึ้นอยู่กับแหล่งที่มา) และLEFT OUTER JOIN ... WHERE right.column IS NULLรูปแบบที่นิยมมักจะเป็นนักแสดงที่แย่ที่สุดเสมอ

Martin Smith มีข้อมูลสนับสนุนที่ดีมากมายในคำตอบของเขาใน SO เช่นกันกัน

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