การตั้งค่า NOCOUNT ON


341

แรงบันดาลใจจากคำถามนี้ที่มีมุมมองที่แตกต่างกันใน SET NOCOUNT ...

เราควรใช้ SET NOCOUNT ON สำหรับ SQL Server หรือไม่ ถ้าไม่ทำไมล่ะ

การแก้ไข 6 ในวันที่ 22 กรกฎาคม 2011 คืออะไร

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

สำหรับทริกเกอร์ ฯลฯ ลูกค้าจะได้รับ "xx rows ที่ได้รับผลกระทบ" หลายครั้งและทำให้เกิดข้อผิดพลาดทุกรูปแบบสำหรับ ORMs บางตัว, MS Access, JPA และอื่น ๆ (ดูการแก้ไขด้านล่าง)

พื้นหลัง:

วิธีปฏิบัติที่ดีที่สุดที่เป็นที่ยอมรับทั่วไป (ฉันคิดว่าจนกระทั่งคำถามนี้) คือการใช้SET NOCOUNT ONในทริกเกอร์และขั้นตอนการจัดเก็บใน SQL Server เราใช้งานได้ทุกที่และ google ฉบับย่อก็แสดงให้เห็นว่ามี SQLPV Server จำนวนมากที่เห็นด้วยเช่นกัน

MSDN กล่าวนี้สามารถทำลาย.net SqlDataAdapter

ตอนนี้สิ่งนี้หมายความว่า SQLDataAdapter นั้นถูก จำกัด เพียงการประมวลผล CRUD อย่างเต็มที่เพราะมันคาดว่าข้อความ "n แถวที่ได้รับผลกระทบ" จะตรงกัน ดังนั้นฉันไม่สามารถใช้:

  • หากมีอยู่เพื่อหลีกเลี่ยงการซ้ำซ้อน (ไม่มีข้อความที่ได้รับผลกระทบแถว) หมายเหตุ: ใช้ด้วยความระมัดระวัง
  • ไม่อยู่ (แถวน้อยกว่าที่คาดไว้
  • กรองการอัพเดทเล็กน้อย (เช่นไม่มีการเปลี่ยนแปลงข้อมูลจริง)
  • ทำการเข้าถึงตารางใด ๆ ก่อน (เช่นการบันทึก)
  • ซ่อนความซับซ้อนหรือ denormlisation
  • ฯลฯ

ในคำถามที่ marc_s (ใครรู้เรื่อง SQL ของเขา) บอกว่าอย่าใช้มัน สิ่งนี้แตกต่างจากที่ฉันคิด (และฉันถือว่าตัวเองมีความสามารถพอสมควรที่ SQL เช่นกัน)

เป็นไปได้ว่าฉันขาดอะไรไปบ้าง (อย่าลังเลที่จะชี้ให้เห็นอย่างชัดเจน) แต่คุณคิดว่ายังไงบ้าง?

หมายเหตุ: เป็นเวลาหลายปีแล้วที่ฉันเห็นข้อผิดพลาดนี้เพราะฉันไม่ได้ใช้ SQLDataAdapter ทุกวันนี้

แก้ไขหลังจากความคิดเห็นและคำถาม:

แก้ไข: ความคิดเพิ่มเติม ...

เรามีหลายไคลเอนต์: หนึ่งอาจใช้ C # SQLDataAdaptor อื่นอาจใช้ nHibernate จาก Java SET NOCOUNT ONเหล่านี้ได้รับผลกระทบในรูปแบบที่แตกต่างกันด้วย

ถ้าคุณคิดว่า procs ที่เก็บไว้เป็นวิธีการมันเป็นรูปแบบที่ไม่ดี (anti-pattern) เพื่อสมมติว่าการประมวลผลภายในบางอย่างทำงานในลักษณะที่เป็นไปตามวัตถุประสงค์ของคุณเอง

แก้ไข 2: ทริกเกอร์แบ่งคำถาม nHibernateซึ่งSET NOCOUNT ONไม่สามารถตั้งค่าได้

(และไม่มันไม่ซ้ำกันนี้ )

แก้ไข 3: ยังมีข้อมูลเพิ่มเติมขอบคุณเพื่อนร่วมงาน MVP ของฉัน

แก้ไข 4: 13 พฤษภาคม 2554

แบ่ง Linq 2 SQL ด้วยเมื่อไม่ได้ระบุ?

แก้ไข 5: 14 มิถุนายน 2554

แบ่ง JPA, proc ที่จัดเก็บพร้อมตัวแปรตาราง: JPA 2.0 รองรับตัวแปรตาราง SQL Server หรือไม่

แก้ไข 6: 15 สิงหาคม 2554

ตารางข้อมูล "แก้ไขแถว" SSMS ต้องการ SET NOCOUNT ON: อัพเดททริกเกอร์ด้วย GROUP BY

แก้ไข 7: 07 Mar 2013

รายละเอียดเชิงลึกเพิ่มเติมจาก @RemusRusanu: การ
เปิด SET NOCOUNT ทำให้เกิดความแตกต่างด้านประสิทธิภาพหรือไม่


@AlexKuznetsov: อะไรคือแนวทาง "Threadsafe" การอ่านที่ดำเนินการอย่างแน่นอนใน EXISTS จะยังคงรวมธุรกรรมที่ค้างชำระอยู่หรือไม่
AnthonyWJones

2
@ Jeremy Seghi: ขอโทษที่ตอบช้า ข้อความ (#rows ที่ได้รับผลกระทบ) เป็นสิ่งที่เครื่องมือไคลเอ็นต์ตีความโดย SSMS และอื่น ๆ : อย่างไรก็ตามมีแพ็คเก็ตที่ส่งมาพร้อมกับข้อมูลนี้ แน่นอนผมตระหนักถึงวิธีการ rowcount @@ ทำงาน ฯลฯ แต่นี้ไม่ได้เป็นจุดของคำถาม ...
GBN

1
ไม่ต้องห่วง. ส่วนตัวฉันเห็นด้วยกับมุมมองของคุณ; ฉันแค่แสดงความคิดเห็นว่าไม่มีความสัมพันธ์โดยตรงระหว่างผลลัพธ์ของ IF / WHERE EXISTS สร้างและ SET NOCOUNT ฉันได้รับผลลัพธ์ที่สอดคล้องกันจากโครงสร้างเหล่านั้นโดยไม่คำนึงถึง NOCOUNT หากคุณมีอะไรพูดเป็นอย่างอื่นโปรดส่งมันมาทางฉัน
Jeremy S

1
@Jeremy Seghi: ถูกต้อง: SET NOCOUNT ON จะระงับเฉพาะแพ็กเก็ตข้อมูลที่ส่งกลับไปยังไคลเอนต์ IF, @@ ROWCOUNT และอื่น ๆ ทั้งหมดจะไม่ได้รับผลกระทบ โอ้และมันหยุด SQLDataAdapters ... :-)
gbn

1
@ Kieren Johnstone: ในความเข้าใจย้อนหลังมันเป็นคำถามที่พูดไม่ดี ฉันต้องการที่จะลงคะแนนเสียงใกล้ชิดหากนี่ไม่ใช่คำถามของฉัน ...
GBN

คำตอบ:


246

ตกลงตอนนี้ฉันได้ทำการวิจัยแล้วนี่คือข้อตกลง:

ในโปรโตคอล TDS SET NOCOUNT ONบันทึกได้เพียง9 ไบต์ต่อข้อความค้นหาในขณะที่ข้อความ "SET NOCOUNT ON" นั้นมีขนาด 14 ไบต์ ฉันเคยคิดว่า123 row(s) affectedถูกส่งคืนจากเซิร์ฟเวอร์เป็นข้อความธรรมดาในแพ็กเก็ตเครือข่ายแยกต่างหาก แต่นั่นไม่ใช่กรณี ในความเป็นจริงโครงสร้างขนาดเล็กที่เรียกว่าDONE_IN_PROCฝังตัวอยู่ในการตอบสนอง ไม่ใช่แพ็กเก็ตเครือข่ายที่แยกต่างหากดังนั้นจึงไม่มีการปัดเศษ

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

นี่คือการวิเคราะห์อย่างละเอียดเกี่ยวกับความไม่สำคัญของSET NOCOUNTการตั้งค่า: http://daleburnett.com/2014/01/everything-ever-wanted-know-set-nocount/


จริง ฉันใช้ SET NOCOUNT ON ตลอดไป แต่ marc_s ชี้ให้เห็นข้อ จำกัด ของ SQLDataAdapter ในคำถามอื่น
gbn

ขอบคุณ ไบต์หรือขนาดไม่ใช่ปัญหาสำหรับฉัน แต่ลูกค้าต้องดำเนินการ มันพึ่งพา SqlDataAdapter ที่ยังคง astounds ฉันแม้ว่า ...
GBN

2
ขอบคุณสำหรับคำตอบ. ฉันจะยอมรับสิ่งนี้เนื่องจากการสืบสวนของคุณซึ่งเรียกข้อมูลเพิ่มเติมและทำงานจากฉัน ฉันไม่เห็นด้วยกับค่าใช้จ่ายแม้ว่ามันอาจมีความสำคัญเช่นเดียวกับคำตอบอื่น ๆ ที่แสดง ไชโย, gbn
gbn

13
มันไม่ได้เป็นจำนวนไบต์ของมันล่าช้าไปกลับไปรอบ ๆ ลวดซึ่งเป็นนักฆ่าประสิทธิภาพ
racingsnail

1
ในสตรีมข้อความ TDS และตัวอย่างคือเมื่อมีการแทรกเฉพาะค่าลงในตาราง DONINPROC(RPC) หรือDONE(batch) ข้อความจะสตรีมกับrowcountชุดแถวได้รับผลกระทบในขณะที่done_countธงtrueไม่คำนึงถึงว่าเป็นNO_COUNT ONขึ้นอยู่กับการดำเนินงาน lib ลูกค้าในกรณีเมื่อแบบสอบถามถืองบเลือกหรือโทร RPC ที่ไม่เลือกก็อาจจำเป็นต้องปิดการใช้งานนับ ... เมื่อคนพิการ, แถวยังคงนับคำสั่งเลือก แต่ธงมีการตั้งค่าDONE_COUNT falseควรอ่านสิ่งที่ลูกค้าของคุณแนะนำ lib เพราะมันจะตีความโทเค็น (ข้อความ) สตรีมแทนคุณ
มิลานจาริ

87

ฉันต้องขุดจำนวนมากเพื่อค้นหาตัวเลขมาตรฐานจริงรอบ ๆ NOCOUNT ดังนั้นฉันจึงคิดว่าฉันจะแบ่งปันข้อมูลสรุปโดยย่อ

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

5
+1 สำหรับผลกระทบกับเคอร์เซอร์สิ่งนี้สอดคล้องกับข้อสังเกตของฉัน
zvolkov

จุดที่ 2 ไม่ถูกต้อง! ฉันหมายถึงบล็อกที่อ้างถึง ไม่เคยเป็น! DONE และ DONEPROC และ DONEINPROC ถูกส่งด้วยขนาดเดียวกันโดยไม่คำนึงว่า NO_COUNT ถูกตั้งค่าเป็น ON หรือ OFF RowCount ยังคงเป็น ULONGLONG (64 bytes) และการตั้งค่าสถานะ DONE_COUNT ยังคงมีอยู่ แต่ค่าบิตเป็น 0 เซิร์ฟเวอร์ SQL จะนับจำนวนแถวอย่างไรก็ตามแม้คุณไม่สนใจอ่านค่าจากโทเค็น DONE หากคุณอ่าน @@ ROWCOUNT คุณจะต้องเพิ่มโทเค็นโทเค็นสตรีมเป็นโทเค็น returnvalue หรือเป็น colmetadata + โทเค็นแถวอื่น!
มิลานจาริ

@MilanJaric: ขอบคุณที่โทรออก คุณช่วยฉันรู้ว่าฉันจะเชื่อมโยงบทความที่ผิด ลิงก์ได้รับการอัปเดตแล้วและบทความสร้างข้อโต้แย้งที่น่าสนใจเพื่อแสดงว่าอาจมีการปรับปรุงประสิทธิภาพเล็กน้อยด้วย SET NOCOUNT ON คุณคิดว่ามีปัญหากับวิธีการเปรียบเทียบที่ใช้หรือไม่?
StriplingWarrior

:) ยังไม่ถูกต้องเกี่ยวกับ SET NOCOUNT OFF / ON ข้อผิดพลาดคือ SP ที่สองไม่มีSET NOCOUNT OFF;และนั่นคือสาเหตุที่พวกเขาคิดว่าพวกเขาไม่ได้รับไบต์พิเศษในการตอบสนอง มาตรฐานที่แม่นยำจะใช้SET NOCOUNT ONในSET NOCOUNT OFFขั้นตอนการจัดเก็บด้านซ้ายและขวา วิธีนี้คุณจะได้รับแพคเกจ TDS กับDONEINPROC (SET NOCOUNT ...)สิบอีกครั้งDONEINPROC (INSERT statement)แล้วRETURNVALUE(@@ROWCOUNT)แล้วRETURNSTATUS 0สำหรับ SP และ DONPROCFinaly เกิดข้อผิดพลาดเนื่องจาก sp ที่สองไม่มีการตั้งค่า NOCOUNT OFF ในร่างกาย!
Milan Jaric

ในการใช้ถ้อยคำใหม่ในสิ่งที่พบ แต่พวกเขาไม่ทราบว่าถ้าคุณมีการดึงเคอร์เซอร์ 1K ก่อนอื่นให้ทำการตั้งค่า NOCOUNT เป็น ON หรือ OFF สำหรับการเชื่อมต่อจากนั้นใช้การเชื่อมต่อเดียวกันกับการเรียกเคอร์เซอร์ดึง 1K ครั้งเพื่อบันทึกแบนด์วิดท์ สถานะการเชื่อมต่อที่แท้จริงสำหรับการเปิดหรือปิด NOCOUNT จะไม่ส่งผลกระทบต่อแบนด์วิดธ์อาจทำให้เกิดความสับสนกับไคลเอนต์ lib เช่น ADO.net หรือ ODBC ดังนั้น "ไม่ได้ใช้ SET NOCOUNT <WHATEVER> ถ้าคุณดูแลเกี่ยวกับแบนด์วิดธ์" :)
มิลาน Jaric

77
  • เมื่อ SET NOCOUNT เปิดอยู่การนับ (ระบุจำนวนแถวที่ได้รับผลกระทบจากคำสั่ง Transact-SQL) จะไม่ถูกส่งกลับ เมื่อ SET NOCOUNT ปิดการนับจะถูกส่งกลับ มันถูกใช้กับคำสั่ง SELECT, INSERT, UPDATE, DELETE ใด ๆ

  • การตั้งค่า SET NOCOUNT ตั้งไว้ที่รันไทม์หรือรันไทม์และไม่ใช่เวลาแยกวิเคราะห์

  • SET NOCOUNT ON ช่วยปรับปรุงประสิทธิภาพของโพรซีเดอร์ (SP)

  • ไวยากรณ์: SET NOCOUNT {ON | ปิด}

ตัวอย่างของ SET NOCOUNT ON:

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

ตัวอย่าง SET NOCOUNT OFF:

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


7
ง่ายและรวดเร็วในการทำความเข้าใจกับภาพหน้าจอ ผลงานยอดเยี่ยม :)
shaijut

35

ฉันเดาว่ามันเป็นปัญหาของ DBA กับนักพัฒนา

ในฐานะที่เป็นนักพัฒนาส่วนใหญ่ฉันจะบอกว่าอย่าใช้มันเว้นแต่คุณจะต้องใช้ประโยชน์ในเชิงบวกอย่างแน่นอนเพราะการใช้มันสามารถทำลายรหัส ADO.NET ของคุณ (ดังที่ได้รับการรับรองจาก Microsoft)

และฉันเดาว่าเป็น DBA คุณจะได้รับมากกว่านี้ - ใช้มันทุกครั้งที่เป็นไปได้เว้นแต่คุณจะต้องป้องกันการใช้งานจริง ๆ

นอกจากนี้หาก devs ของคุณเคยใช้ "RecordsAffected" ที่ถูกส่งกลับโดยExecuteNonQueryการเรียกใช้เมธอดของ ADO.NET คุณกำลังมีปัญหาหากทุกคนใช้SET NOCOUNT ONตั้งแต่ในกรณีนี้ ExecuteNonQuery จะส่งคืน 0 เสมอ

ดูโพสต์บล็อกของ Peter Bromberg และดูตำแหน่งของเขา

ดังนั้นมันจึงทำให้ผู้ที่กำหนดมาตรฐาน :-) เดือด

มาร์ค


เขาเป็นคนที่เกี่ยวกับ CRUD ง่ายแม้ว่า: ตารางข้อมูลที่เขากล่าวสามารถใช้ XML เพื่อส่งหลายแถวเพื่อหลีกเลี่ยงการเดินทางไปรอบ ฯลฯ
GBN

ฉันเดาว่าถ้าคุณไม่เคยใช้ SqlDataAdapters และคุณไม่เคยตรวจสอบและพึ่งพาหมายเลข "บันทึกที่ได้รับผลกระทบ" ที่ส่งคืนโดย ExecuteNonQuery (เช่นถ้าคุณใช้บางอย่างเช่น Linq-to-SQL หรือ NHibernate) คุณอาจไม่มีปัญหาใด ๆ ใช้ SET NOCOUNT ON ใน procs ที่เก็บไว้ทั้งหมด
marc_s

12

หากคุณกำลังบอกว่าคุณอาจมีลูกค้าที่แตกต่างกันเช่นกันมีปัญหากับ ADO แบบคลาสสิกหาก SET NOCOUNT ไม่ได้ตั้งไว้

หนึ่งในประสบการณ์ของฉันเป็นประจำ: หากโพรซีเดอร์ที่เก็บประมวลผลคำสั่งจำนวนมาก (และส่งคืนข้อความ "แถวที่ได้รับผลกระทบ xxx" จำนวนมาก) ADO ดูเหมือนจะไม่จัดการสิ่งนี้และส่งข้อผิดพลาด"ไม่สามารถเปลี่ยนคุณสมบัติ ActiveConnection ของวัตถุชุดระเบียน ซึ่งมีวัตถุคำสั่งเป็นแหล่งที่มา "

ดังนั้นโดยทั่วไปฉันจึงสนับสนุนให้เปิดใช้งานเว้นแต่จะไม่มีเหตุผลที่ดีจริงๆ คุณอาจพบว่าเหตุผลที่ดีจริง ๆ ซึ่งฉันต้องไปอ่านเพิ่มเติม


9

ด้วยความเสี่ยงที่จะทำให้สิ่งต่าง ๆ มีความซับซ้อนฉันขอแนะนำให้ใช้กฎที่แตกต่างกันเล็กน้อยสำหรับผู้ที่ฉันเห็นด้านบน

  • ตั้งเสมอNOCOUNT ONที่ด้านบนของ proc ที่ก่อนที่คุณจะทำผลงานใด ๆ ใน proc แต่ยัง เสมอSET NOCOUNT OFFกันอีกครั้งก่อนที่จะกลับระเบียนใด ๆ จาก proc เก็บไว้

ดังนั้น "โดยทั่วไปแล้วให้ nocount ต่อยกเว้นเมื่อคุณส่งคืน resultset" ฉันไม่รู้วิธีการใด ๆ ที่สามารถทำลายรหัสลูกค้าใด ๆ ได้หมายความว่ารหัสลูกค้าไม่จำเป็นต้องรู้อะไรเกี่ยวกับ proc internals และมันไม่ได้เป็นภาระโดยเฉพาะอย่างยิ่ง


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

ปัญหาของกฎนี้คือการทดสอบยากกว่า "SET NOCOUNT ON อยู่ที่ส่วนบนสุดของ proc หรือไม่"; ฉันสงสัยว่าเครื่องมือวิเคราะห์ SQL เช่น Sql Enlight สามารถทดสอบสำหรับการจัดเรียงของสิ่งที่ ... เพิ่มในรายการสิ่งที่ต้องทำในระยะยาวสำหรับ SQL ของฉันจัดรูปแบบโครงการ :)
เต่า

5

เกี่ยวกับต้นเหตุของการทำลาย NHibernate ฉันมีประสบการณ์นั้นโดยตรง โดยทั่วไปเมื่อ NH ทำการอัพเดทมันคาดว่าจะมีผลกระทบกับแถวจำนวนหนึ่ง ด้วยการเพิ่ม SET NOCOUNT ON ให้กับทริกเกอร์คุณจะได้รับจำนวนแถวกลับไปที่ NH ที่คาดไว้ซึ่งจะแก้ไขปัญหา ดังนั้นใช่ฉันขอแนะนำให้ปิดการใช้ทริกเกอร์หากคุณใช้ NH

เกี่ยวกับการใช้งาน SP มันเป็นเรื่องของความชอบส่วนตัว ฉันได้ปิดการนับแถวเสมอ แต่แล้วอีกครั้งไม่มีข้อโต้แย้งที่แข็งแกร่งจริงอย่างใดอย่างหนึ่ง

ในบันทึกอื่นคุณควรพิจารณาย้ายออกจากสถาปัตยกรรมที่อิง SP จริง ๆ แล้วคุณจะไม่มีคำถามนี้


1
ฉันไม่เห็นด้วยกับการย้ายออกจาก procs ที่เก็บไว้ นี่หมายความว่าเราต้องมี SQL ที่เหมือนกันในฐานรหัสลูกค้าที่แตกต่างกัน 2 แห่งและไว้วางใจตัวแปลงสัญญาณไคลเอ็นต์ของเรา เราเป็นนักพัฒนา DBA และคุณไม่ได้หมายถึง "SET NOCOUNT ON " ใช่ไหม
gbn

@CodeBlend: เพียง Google มันมากกว่าที่คุณต้องการ อย่างไรก็ตาม ... stackoverflow.com/a/4040466/27535
gbn

3

ฉันต้องการยืนยันตัวเองว่า 'SET NOCOUNT ON' ไม่ได้บันทึกแพ็กเก็ตเครือข่ายหรือไปกลับ

ฉันใช้การทดสอบ SQLServer 2017 บนโฮสต์อื่น (ฉันใช้ VM) create table ttable1 (n int); insert into ttable1 values (1),(2),(3),(4),(5),(6),(7) go create procedure procNoCount as begin set nocount on update ttable1 set n=10-n end create procedure procNormal as begin update ttable1 set n=10-n end จากนั้นฉันติดตามแพ็คเก็ตบนพอร์ต 1433 ด้วยเครื่องมือ 'Wireshark': ปุ่ม 'ตัวกรองการจับ' -> 'พอร์ต 1433'

exec procNoCount

นี่คือแพ็คเก็ตการตอบสนอง: 0000 00 50 56 c0 00 08 00 0c 29 31 3f 75 08 00 45 00 0010 00 42 d0 ce 40 00 40 06 84 0d c0 a8 32 88 c0 a8 0020 32 01 05 99 fe a5 91 49 e5 9c be fb 85 01 50 18 0030 02 b4 e6 0e 00 00 04 01 00 1a 00 35 01 00 79 00 0040 00 00 00 fe 00 00 e0 00 00 00 00 00 00 00 00 00

exec procNormal

นี่คือแพ็คเก็ตการตอบสนอง: 0000 00 50 56 c0 00 08 00 0c 29 31 3f 75 08 00 45 00 0010 00 4f d0 ea 40 00 40 06 83 e4 c0 a8 32 88 c0 a8 0020 32 01 05 99 fe a5 91 49 e8 b1 be fb 8a 35 50 18 0030 03 02 e6 1b 00 00 04 01 00 27 00 35 01 00 ff 11 0040 00 c5 00 07 00 00 00 00 00 00 00 79 00 00 00 00 0050 fe 00 00 e0 00 00 00 00 00 00 00 00 00

ในบรรทัด 40 ฉันสามารถดู '07' ซึ่งเป็นจำนวนของ 'แถว (s) ที่ได้รับผลกระทบ' มันรวมอยู่ในแพ็คเก็ตการตอบสนอง ไม่มีแพ็กเก็ตพิเศษ

อย่างไรก็ตามมี 13 ไบต์พิเศษที่สามารถบันทึกได้ แต่อาจไม่คุ้มค่ากว่าการลดชื่อคอลัมน์ (เช่น 'ManagingDepartment' เป็น 'MD')

ดังนั้นฉันไม่เห็นเหตุผลที่จะใช้เพื่อประสิทธิภาพ

แต่อย่างที่คนอื่นพูดถึงมันสามารถทำลาย ADO.NET และฉันก็สะดุดกับปัญหาการใช้ python: MSSQL2008 - Pyodbc - SQL ก่อนหน้านี้ไม่ใช่แบบสอบถาม

ดังนั้นอาจเป็นนิสัยที่ดียัง ...


1
SET NOCOUNT ON;

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


2
โปรดทราบว่า @@ ROWCOUNT ยังคงตั้งค่าไว้ SET NOCOUNT ON ไม่แสดงการตอบสนองเพิ่มเติมใด ๆ ที่ SQL Server ส่งไปยังไคลเอ็นต์ ดูคำตอบที่ได้รับการยอมรับดังกล่าวข้างต้นโปรด
GBN

1

เปิด NOCOUNT โค้ดด้านบนจะหยุดข้อความที่สร้างขึ้นโดยเอ็นจินเซิร์ฟเวอร์ sql ไปที่หน้าต่างผลลัพธ์ด้านหน้าหลังจากการดำเนินการคำสั่ง DML / DDL

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


1

ที่เดียวที่SET NOCOUNT ONสามารถช่วยได้จริงๆคือที่ที่คุณทำแบบสอบถามในลูปหรือเคอร์เซอร์ สิ่งนี้สามารถเพิ่มทราฟฟิกเครือข่ายได้มาก

CREATE PROCEDURE NoCountOn
AS
set nocount on
    DECLARE @num INT = 10000
    while @num > 0
    begin
       update MyTable SET SomeColumn=SomeColumn
       set @num = @num - 1
    end
GO


CREATE PROCEDURE NoCountOff
AS
set nocount off
    DECLARE @num INT = 10000
    while @num > 0
    begin
       update MyTable SET SomeColumn=SomeColumn
       set @num = @num - 1
    end
GO

เมื่อเปิดสถิติลูกค้าใน SSMS การทำงานEXEC NoCountOnและEXEC NoCountOffแสดงว่ามีการรับส่งข้อมูลเพิ่มเติม 390KB ใน NoCountOff หนึ่งรายการ:

สถิติลูกค้า

อาจไม่เหมาะที่จะทำแบบสอบถามในวงหรือเคอร์เซอร์ แต่เราไม่ได้อยู่ในโลกอุดมคติเช่นกัน :)


0

ฉันรู้ว่ามันเป็นคำถามที่ค่อนข้างเก่า แต่สำหรับการอัพเดท

วิธีที่ดีที่สุดในการใช้ "SET NOCOUNT ON" คือการใส่มันเป็นคำสั่งแรกใน SP ของคุณและตั้งเป็น OFF อีกครั้งก่อนคำสั่ง SELECT ล่าสุด


0

SET NOCOUNT ON ยังอนุญาตให้เข้าถึงแถวที่ได้รับผลกระทบเช่นนี้:

SET NOCOUNT ON

DECLARE @test TABLE (ID int)

INSERT INTO @test
VALUES (1),(2),(3)

DECLARE @affectedRows int = -99  

DELETE top (1)
  FROM @test
SET @affectedRows = @@rowcount

SELECT @affectedRows as affectedRows

ผล

affectedRows

1

ข้อความ

คำสั่งสำเร็จแล้ว

เวลาที่สำเร็จ: 2020-06-18T16: 20: 16.9686874 + 02: 00


-1

ฉันไม่รู้วิธีทดสอบ SET NOCOUNT ON ระหว่างไคลเอนต์และ SQL ดังนั้นฉันจึงทดสอบพฤติกรรมที่คล้ายกันสำหรับคำสั่ง SET อื่น ๆ "SET TRANSACTION ISOLATION LEOL LEAD READ UNCIMMITTED"

ฉันส่งคำสั่งจากการเชื่อมต่อของฉันเปลี่ยนพฤติกรรมเริ่มต้นของ SQL (READ COMMITTED) และมันก็เปลี่ยนไปสำหรับคำสั่งถัดไป เมื่อฉันเปลี่ยนระดับ ISOLATION ภายในโพรซีเดอร์ที่เก็บไว้มันไม่เปลี่ยนพฤติกรรมการเชื่อมต่อสำหรับคำสั่งถัดไป

ข้อสรุปปัจจุบัน

  1. การเปลี่ยนการตั้งค่าภายในกระบวนงานที่เก็บไว้จะไม่เปลี่ยนการตั้งค่าเริ่มต้นของการเชื่อมต่อ
  2. การเปลี่ยนการตั้งค่าโดยการส่งคำสั่งโดยใช้ ADOCOnnection จะเปลี่ยนลักษณะการทำงานเริ่มต้น

ฉันคิดว่าสิ่งนี้เกี่ยวข้องกับคำสั่ง SET อื่น ๆ เช่น "SET NOCOUNT ON"


จุดที่ 1 ของคุณข้างต้นบอกเป็นนัยหรือไม่ว่าคุณไม่จำเป็นต้องตั้งค่า NOCOUNT OFF ในตอนท้ายเพราะไม่ส่งผลกระทบต่อสภาพแวดล้อมของโลก
funkymushroom

ฉันไม่แน่ใจว่าเป็นสิ่งที่เขาหมายถึงจุดที่ 1 แต่ในการทดสอบของฉันใช่เห็นได้ชัดว่าสภาพแวดล้อมทั่วโลกไม่ได้รับผลกระทบจาก SET NOCOUNT ON ภายในกระบวนงานที่เก็บไว้
Doug

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

-1

ถ้า (ตั้งค่าไม่นับ == ปิด)

{จากนั้นจะเก็บข้อมูลจำนวนระเบียนที่ได้รับผลกระทบเพื่อลดประสิทธิภาพ} อื่น {จะไม่ติดตามบันทึกการเปลี่ยนแปลงดังนั้นจึงปรับปรุง perfomace}}


-1

บางครั้งแม้แต่สิ่งที่ง่ายที่สุดก็สามารถสร้างความแตกต่างได้ SET NOCOUNT ONหนึ่งในรายการง่ายๆเหล่านี้ที่ควรจะเป็นส่วนหนึ่งของทุกขั้นตอนการเก็บคือ รหัสนี้หนึ่งบรรทัดวางไว้ที่ด้านบนของกระบวนงานที่เก็บไว้ปิดข้อความที่ SQL Server ส่งกลับไปยังไคลเอนต์หลังจากที่ดำเนินการคำสั่ง T-SQL แต่ละคำสั่ง นี้จะดำเนินการทั้งหมดSELECT, INSERT, UPDATEและDELETEงบ การมีข้อมูลนี้มีประโยชน์เมื่อคุณเรียกใช้คำสั่ง T-SQL ในหน้าต่างแบบสอบถาม แต่เมื่อเรียกใช้กระบวนงานที่เก็บไว้ไม่จำเป็นต้องให้ข้อมูลนี้ถูกส่งกลับไปยังไคลเอนต์

ด้วยการลบค่าใช้จ่ายพิเศษนี้ออกจากเครือข่ายจะสามารถปรับปรุงประสิทธิภาพโดยรวมสำหรับฐานข้อมูลและแอปพลิเคชันของคุณได้อย่างมาก

หากคุณยังต้องการรับจำนวนแถวที่ได้รับผลกระทบจากคำสั่ง T-SQL ที่ดำเนินการอยู่คุณยังสามารถใช้@@ROWCOUNTตัวเลือกนี้ได้ โดยการออกSET NOCOUNT ONฟังก์ชันนี้ ( @@ROWCOUNT) ยังคงใช้งานได้และยังสามารถใช้ในขั้นตอนการจัดเก็บของคุณเพื่อระบุจำนวนแถวที่ได้รับผลกระทบจากคำสั่ง

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