SQL Server NOLOCK และเชื่อมต่อ


153

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

คำถามของฉันคือ; หากฉันใช้การรวมฉันต้องระบุคำใบ้ NOLOCK สำหรับสิ่งเหล่านั้นด้วยหรือไม่

ตัวอย่างเช่น คือ:

SELECT * FROM table1 a WITH (NOLOCK)
INNER JOIN table2 b WITH (NOLOCK) ON a.ID = b.ID

เทียบเท่ากับ:

SELECT * FROM table1 a WITH (NOLOCK)
INNER JOIN table2 b ON a.ID = b.ID

หรือฉันจะต้องระบุ(NOLOCK)คำใบ้ในการเข้าร่วมเพื่อให้แน่ใจว่าฉันไม่ได้ล็อคตารางการเข้าร่วม?

คำตอบ:


166

ฉันจะไม่พูดกับ READ UNCOMMITTEDข้อโต้แย้ง แต่เป็นคำถามเดิมของคุณ

ใช่คุณต้องการWITH(NOLOCK)ในการเข้าร่วมแต่ละตาราง ไม่คำค้นหาของคุณไม่เหมือนกัน

ลองออกกำลังกายนี้ เริ่มต้นธุรกรรมและแทรกแถวใน table1 และ table2 อย่ากระทำหรือย้อนกลับธุรกรรม ณ จุดนี้แบบสอบถามแรกของคุณจะกลับมาสำเร็จและรวมแถวที่ไม่มีข้อผูกมัดไว้ ข้อความค้นหาที่สองของคุณจะไม่กลับมาเนื่องจาก table2 ไม่มีWITH(NOLOCK)คำใบ้ไว้


18

ฉันค่อนข้างแน่ใจว่าคุณต้องระบุNOLOCKสำหรับแต่ละคำJOINในแบบสอบถาม แต่ประสบการณ์ของฉันถูก จำกัด ไว้ที่ SQL Server 2005

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

[SQL Server 2008 R2]

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

[SQL Server 2005]

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

นอกจากนี้โปรดสังเกต - และสิ่งนี้ใช้ได้กับทั้งปี 2005 และ 2008:

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


@ In Sane: น่าสนใจ ... ขอบคุณสำหรับสิ่งนั้น ... ฉันสมมติว่าฉันไม่ได้ทำอันตรายโดยรวมมันไว้ใน JOINS แม้ว่ามันจะไม่จำเป็นเลยเหรอ? เอกสารเกี่ยวกับ NOLOCK ค่อนข้างเบาบางดังที่คุณพูดถึง ฉันมีปัญหาในการหาข้อสรุปใด ๆ เอง
DanP

2
@InSane: คุณได้รับข้อมูลนี้จากที่ไหน ดูเหมือนว่าจะขัดแย้งกับคำตอบที่ยอมรับ
เจย์ซัลลิแวน

1
@notfed - อ้างอิง link technet.microsoft.com/en-us/library/ms187373(v=sql.105).aspx - คุณสามารถเปลี่ยนรุ่นฐานข้อมูลที่ด้านบนเพื่อเปรียบเทียบบทความเดียวกันสำหรับ db รุ่นต่าง ๆ
Jagmag

2
ข้อความในปี 2005 พูดถึง VIEWS ดังนั้นถ้าคุณทำ "จาก myview with (nolock)" มันบอกว่า nolock นั้นแพร่กระจายไปยังตารางทั้งหมดและมุมมองที่เกี่ยวข้องใน myview (คุณอาจมี 10 joins ในนั้น) ไม่แน่ใจว่าข้อความ 2008 มีความหมายตรงตามที่เพิ่ม "เข้าถึงได้โดยแผนแบบสอบถาม" เพิ่มเติมจากมุมมอง
Thierry_S

9

ทั้ง คุณตั้งค่าระดับการแยกREAD UNCOMMITTEDที่ดีกว่าให้คำแนะนำการล็อคเฉพาะ หรือดีกว่ายังคงถ้าคุณดูแลเกี่ยวกับรายละเอียดเช่นความสอดคล้องใช้แยกภาพรวม


@Remus: ฉันไม่แน่ใจว่าฉันสามารถใช้ READ UNCOMMITTED ในกรณีของฉันได้เพราะฉันเข้าถึงการเชื่อมต่อผ่าน NHibernate เพื่อทำการโทร ADO.NET แบบพิเศษ สามารถระบุแบบอินไลน์ในแบบสอบถามได้หรือไม่หรือจะเป็นไปตามระดับธุรกรรมที่มีอยู่ในธุรกรรม NHibernate หรือไม่
DanP

ปิดการโทรusing (TransactionScope scope=new TransactionScope(..., TransactionOptions) {...}และตั้งค่าIsolationLevelบนตัวเลือก: msdn.microsoft.com/en-us/library/…
Remus Rusanu

@Remus: น่าเสียดายที่การจัดการธุรกรรมได้รับการดูแลในระดับที่สูงกว่านี้มากดังนั้นจึงไม่ใช่ตัวเลือก
DanP

ฉันเห็น. จากนั้นเพื่อตอบคำถามของคุณ: NOLOCK เป็นคำใบ้ของตารางและเช่นนั้นจะใช้กับ rowset ที่เพิ่มเข้ามา (ตารางมุมมอง TVF เป็นต้น) หากคุณมีหลาย rowets เข้าร่วมในแบบสอบถามแต่ละคนจะต้องมีคำใบ้ NOLOCK ของตัวเอง
Remus Rusanu

2
แต่คุณคิดว่าการแยกสแน๊ปช็อตหรือไม่ ALTER DATABASE ... SET READ_COMMITTED_SNAPSHOT ON;. ผลลัพธ์ที่ได้นั้นน่าประทับใจเนื่องจากการอ่านที่ผู้อ่านปกติทุกคนอ่านกลายเป็นสแน็ปช็อตล็อคฟรี แต่ไม่เปลี่ยนแปลง ต้นทุนเพิ่มขึ้นเมื่อtempdbโหลด: msdn.microsoft.com/en-us/library/ms175492.aspx
Remus Rusanu
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.