คำแนะนำ NOLOCK เปลี่ยนลำดับของบันทึกที่ส่งคืน


11

มีดัชนีคลัสเตอร์บนโต๊ะเป็นฟิลด์ClientLastName

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

ความแตกต่างในการสั่งซื้อสามารถอธิบายได้อย่างไร

ดึงข้อมูลเพิ่มเติมจากความคิดเห็น:

  1. ไม่มีคำสั่งซื้อโดย ดัชนีที่ไม่ใช่คลัสเตอร์ควรบังคับใช้คำสั่งหรือไม่

  2. คิวรียังคงส่งคืนคำสั่งซื้อที่แตกต่างกันแม้ว่าจะใช้คำใบ้ดัชนีที่ระบุดัชนีคลัสเตอร์ พวกเขาควร? ฉันสงสัยว่าทำไมnolockการเปลี่ยนแปลงลำดับของระเบียนที่ส่งคืนโดยไม่มีการเปลี่ยนแปลงแผน

  3. ฉันทำ WinDiff กับพวกเขา - เหมือนกันยกเว้น [the] (nolock)[คำใบ้แบบสอบถาม]


21
คำใบ้ไม่เปลี่ยนคำสั่งซื้อ - เนื่องจากไม่มีคำสั่งซื้อที่สามารถเปลี่ยนแปลงได้
a_horse_with_no_name

คำตอบ:


47

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

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

นี้อาจจะเป็นนามธรรมมาก แต่สามารถแสดงให้เห็นได้ง่ายขึ้นด้วยคำสั่งโดยใช้ฟังก์ชั่นที่ไม่มีเอกสารกับฐานข้อมูล AdventureWorks2012

USE AdventureWorks2012;
GO
-- Appears to be ordered by BusinessEntityID
-- File:Page:Slot goes up and down several times
-- Show physical locations with sys.fn_PhysLocFormatter (undocumented)
SELECT
    P.BusinessEntityID,
    [(File:Page:Slot)] =
        sys.fn_PhysLocFormatter(%%physloc%%)
FROM Person.Person AS P;

-- Same query with TABLOCK or NOLOCK
-- Allocation-order (IAM) scan
-- Now appears to be ordered by File:Page:Slot instead of BusinessEntityID
SELECT P.BusinessEntityID,
    [(File:Page:Slot)] =
        sys.fn_PhysLocFormatter(%%physloc%%)
FROM Person.Person AS P WITH (NOLOCK);

ผลลัพธ์การค้นหา

แบบสอบถามที่ยืมมามีการปรับเปลี่ยนเล็กน้อยจากพอลไวท์

ในที่สุดเพื่อให้ชัดเจนคำตอบนี้เกี่ยวกับลักษณะที่ปรากฏของชุดผลลัพธ์ที่ได้รับคำสั่ง มีไม่มีการรับประกันเพื่อนำเสนอORDER BYโดยไม่ต้องระดับบนสุด

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


7
ดีมากเจาะจงกว่าความพยายามของฉันที่ไม่ได้รับการยอมรับ แน่นอนว่าปมนั้นอยู่ในสองย่อหน้าสุดท้ายของคุณ "ทำไม" ไม่สำคัญในท้ายที่สุด บางทีคุณอาจมีโชคที่ดีกว่าที่จะทำคอร์ดนั้นได้ดีกว่าที่ฉันทำ
Aaron Bertrand

12

เมื่อฉันเพียงแค่ถ่ายโอนข้อมูลทั้งหมดจากตาราง

... จากนั้นคุณไม่ควรคาดหวังคำสั่งใด ๆ อันที่จริงแล้วการสืบค้นที่เหมือนกันหลายครั้งอาจกลับมาเรียงลำดับที่แตกต่างกันโดยไม่มีการเตือน เหตุผลก็คือข้อความค้นหาทั้งสองของคุณ - ซึ่งเป็นข้อความค้นหา "แตกต่าง" ซึ่งเป็นไปได้มากที่สุดเนื่องจากข้อความค้นหาที่แตกต่างกันไม่ใช่เพราะคำใบ้ - มีแผนการดำเนินการที่แตกต่างกัน (และความแตกต่างอาจบอบบางเช่น iterator ทั้งแผน แต่มีordered: trueเพียงหนึ่งเดียวหรือจำนวนแถวที่แตกต่างกันอย่างมากมายเนื่องจากมีการรวบรวมก่อนการเปลี่ยนแปลงข้อมูลที่สำคัญ) อาจเป็นไปได้ว่าการสแกนคำสั่งจัดสรรได้รับการดำเนินการตามที่ James อธิบายไว้อย่างถูกต้องในคำตอบของเขา

ไม่ว่าในกรณีใดเนื่องจากคุณกำลังเรียกใช้แบบสอบถามโดยไม่มีORDER BYSQL Server จะบอกว่าคุณไม่สนใจเกี่ยวกับคำสั่งซื้อและจะปิดและกำหนดวิธีที่มีประสิทธิภาพมากที่สุดในการส่งคืนแถว )

ให้ฉันทำให้ชัดเจนมาก:

หากคุณต้องการหรือคาดว่าจะมีคำสั่งซื้อเพิ่มคำสั่ง ORDER BY

สิ่งนี้เกิดขึ้นก่อนหน้านี้:

และฉัน blogged เกี่ยวกับเรื่องนี้:

นี่คือข้อความจากหลังที่ย้ำสิ่งที่ฉันพูดเพื่อที่อยู่ความคิดเห็นของคุณเกี่ยวกับการใช้คำใบ้ดัชนีแทนORDER BYข้อ:

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

Conor Cunningham คนฉลาดผู้รับผิดชอบโดยตรงมากกับสิ่งที่ SQL Server ทำเมื่อประมวลผลแบบสอบถามสำหรับคุณ - ยังบล็อกเกี่ยวกับที่นี่:

โปรดอ่านและเพิ่มส่วนORDER BYคำสั่งของคุณก่อนที่จะบ่นเกี่ยวกับการเรียงลำดับที่แตกต่างกันหรือไม่คาดคิด


11

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

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