ทำไมผู้คนถึงเกลียดเคอร์เซอร์ SQL มาก? [ปิด]

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

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

อะไรคือสาเหตุของความเกลียดชังอย่างบ้าคลั่งในระดับนี้? 'ผู้มีอำนาจที่มีชื่อเสียง' บางส่วนได้ออก fatwa ต่อต้านเคอร์เซอร์หรือไม่? ความชั่วร้ายที่ไม่อาจบรรยายได้แฝงตัวอยู่ในหัวใจของเคอร์เซอร์ที่ทำลายศีลธรรมของเด็กหรืออะไรสักอย่าง?

คำถาม Wiki สนใจคำตอบมากกว่าตัวแทน

ข้อมูลที่เกี่ยวข้อง:

เคอร์เซอร์กรอไปข้างหน้าของเซิร์ฟเวอร์ SQL

แก้ไข: ให้ฉันแม่นยำกว่านี้: ฉันเข้าใจว่าไม่ควรใช้ เคอร์เซอร์แทนการดำเนินการเชิงสัมพันธ์ปกติ; นั่นไม่ใช่เรื่องง่าย สิ่งที่ฉันไม่เข้าใจคือผู้คนพยายามหลีกทางให้หลีกเลี่ยงเคอร์เซอร์เหมือนมี cooties หรืออะไรสักอย่าง แม้ว่าเคอร์เซอร์จะเป็นวิธีแก้ปัญหาที่ง่ายกว่าและ/หรือมีประสิทธิภาพมากกว่าก็ตาม มันเป็นความเกลียดชังที่ไม่มีเหตุผลที่ทำให้ฉันงุนงง ไม่ใช่ประสิทธิภาพทางเทคนิคที่ชัดเจน


person Community    schedule 13.11.2008    source แหล่งที่มา
comment
ฉันคิดว่าการแก้ไขของคุณบอกทุกอย่างแล้ว... ในสถานการณ์ เกือบ ทุกสถานการณ์ (ที่ฉันเจอ) มีวิธีแทนที่เคอร์เซอร์ด้วยสถานการณ์ตามชุดที่มีประสิทธิภาพดีกว่า คุณพูดง่ายๆ แต่คุณเข้าใจความแตกต่าง   -  person StingyJack    schedule 13.11.2008
comment
ฉันชอบแท็กของคำถามนี้!   -  person sep332    schedule 14.11.2008
comment
ส่วนที่เกี่ยวข้องกับขีดจำกัด CTE แบบเรียกซ้ำที่เป็น 32 นั้นไร้สาระ สมมุติว่าคุณกำลังคิดถึงทริกเกอร์แบบเรียกซ้ำและสูงสุด @@NESTLEVEL จาก 32 สามารถตั้งค่าในการสืบค้นด้วย OPTION (MAXRECURSION N) โดยค่าเริ่มต้น 100 และ 0 หมายถึงไม่จำกัด   -  person Martin Smith    schedule 02.11.2012
comment
@MartinSmith: ขีดจำกัดเริ่มต้นคือตอนนี้ 100 และสูงสุดคือ 32K sql-server-helper.com/error-messages/msg-310.aspx   -  person Steven A. Lowe    schedule 12.01.2016
comment
ไม่ มันยังคงเหมือนเดิมทุกประการกับตอนที่ฉันแสดงความคิดเห็นและใน SQL Server ทุกเวอร์ชันที่รองรับ CTE แบบเรียกซ้ำ ดังที่ลิงก์ของคุณระบุว่า เมื่อระบุ 0 จะไม่มีการนำขีดจำกัดไปใช้   -  person Martin Smith    schedule 12.01.2016
comment
@MartinSmith: ขอบคุณ ความผิดพลาดของฉัน - ข้อผิดพลาดสองครั้งจริง ๆ แล้ว;) ครั้งแรกอ่านการอ้างอิงผิด (ฉันถือว่าขีด จำกัด 32K = 'ไม่ จำกัด ') และอย่างที่สองเป็นสาเหตุที่ผิด - ในตัวอย่างที่อ้างถึง ขีด จำกัด การเรียกซ้ำที่ 32 มาจาก ฟังก์ชันเรียกซ้ำ ไม่ใช่ CTE ตอนนั้นฉันอาจใช้ SQL Server 2000 หรืออาจจะเป็นปี 2008 หวังว่าตอนนี้จะดีกว่านี้ :) แก้ไขคำถามเพื่อชี้แจง - ขอขอบคุณการแก้ไขของคุณ!   -  person Steven A. Lowe    schedule 12.01.2016


คำตอบ (13)


"ค่าใช้จ่าย" ที่มีเคอร์เซอร์เป็นเพียงส่วนหนึ่งของ API เคอร์เซอร์คือการทำงานของส่วนต่างๆ ของ RDBMS ภายใต้ประทุน บ่อยครั้งที่ CREATE TABLE และ INSERT มีคำสั่ง SELECT และการนำไปใช้งานก็คือการใช้เคอร์เซอร์ภายในที่ชัดเจน

การใช้ "ตัวดำเนินการตามชุด" ระดับที่สูงกว่าจะรวมผลลัพธ์ของเคอร์เซอร์ไว้ในชุดผลลัพธ์ชุดเดียว ซึ่งหมายความว่า API ไปมาน้อยลง

เคอร์เซอร์เกิดขึ้นก่อนภาษาสมัยใหม่ซึ่งมีคอลเลกชันชั้นหนึ่ง Old C, COBOL, Fortran ฯลฯ ต้องประมวลผลแถวทีละแถว เนื่องจากไม่มีแนวคิดเรื่อง "การรวบรวม" ที่สามารถนำมาใช้กันอย่างแพร่หลาย Java, C#, Python ฯลฯ มีโครงสร้างรายการระดับเฟิร์สคลาสเพื่อเก็บชุดผลลัพธ์

ปัญหาที่ช้า

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

เขียน SQL อย่างง่ายเพื่อแทนที่ลูปเคอร์เซอร์ที่ซ้อนกันด้วยการรวม และเคอร์เซอร์แบบแบนเดี่ยวสามารถทำให้โปรแกรมรันในครั้งที่ 100 [พวกเขาคิดว่าฉันเป็นเทพแห่งการเพิ่มประสิทธิภาพ ทั้งหมดที่ฉันทำคือแทนที่ลูปที่ซ้อนกันด้วยการรวม ยังคงใช้เคอร์เซอร์อยู่]

ความสับสนนี้มักนำไปสู่การฟ้องร้องเคอร์เซอร์ อย่างไรก็ตาม ปัญหาไม่ใช่เคอร์เซอร์ แต่เป็นการใช้เคอร์เซอร์ในทางที่ผิดนั่นเอง

ปัญหาขนาด

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

ทางเลือก

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

person Community    schedule 13.11.2008
comment
เคอร์เซอร์คือวิธีการทำงานของ RDBMS ภายใต้ประทุน หากคุณหมายถึง SQL Server โดยเฉพาะ ตกลง ก็ได้ ฉันไม่รู้เรื่องนั้น แต่ฉันได้ทำงานเกี่ยวกับภายในของ RDBMS หลายตัว (และ ORDBMS) (ภายใต้ Stonebraker) และไม่มีใครทำอย่างนั้น เช่น: Ingres ใช้จำนวนเท่าใดเพื่อผลลัพธ์ชุดสิ่งอันดับภายใน - person Richard T; 28.12.2008
comment
@Richard T: ฉันกำลังทำงานกับข้อมูลมือสองเกี่ยวกับแหล่ง RDBMS ฉันจะแก้ไขแถลงการณ์ - person S.Lott; 28.12.2008
comment
ฉันเคยเห็นการดำเนินการวนซ้ำแบบมหากาพย์อย่างแท้จริงซึ่งเขียนออกมาเป็นเคอร์เซอร์จำนวนมาก ฉันก็ยังเห็นพวกเขาอยู่เหมือนกัน มันยากที่จะเชื่อ - person RussellH; 30.12.2008

เคอร์เซอร์ทำให้ผู้คนใช้กรอบความคิดแบบขั้นตอนมากเกินไปกับสภาพแวดล้อมที่ถูกกำหนดไว้

และพวกมันช้า!!!

จาก SQLTeam:

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

person Community    schedule 13.11.2008
comment
บทความนี้มีอายุ 7 ปีแล้ว คุณคิดว่าบางทีอาจมีการเปลี่ยนแปลงในระหว่างนี้หรือไม่? - person Steven A. Lowe; 13.11.2008
comment
ฉันยังคิดว่าเคอร์เซอร์ช้ามากและโดยทั่วไปควรหลีกเลี่ยง อย่างไรก็ตาม หาก OP อ้างถึงคำถามที่ฉันคิดว่าเป็นเช่นนั้น เคอร์เซอร์ก็เป็นวิธีแก้ปัญหาที่ถูกต้อง (การสตรีมบันทึกทีละรายการเนื่องจากข้อจำกัดของหน่วยความจำ) - person rmeador; 13.11.2008
comment
บทความที่อัปเดตไม่ได้แก้ไขการวัดความเร็วสัมพัทธ์ แต่มีการปรับปรุงและทางเลือกที่ดีบางประการ โปรดทราบว่าบทความต้นฉบับบอกว่าเคอร์เซอร์เร็วกว่าลูปในขณะที่ 50 เท่าซึ่งน่าสนใจ - person Steven A. Lowe; 13.11.2008
comment
โดยส่วนตัวฉันคิดว่าถ้าคุณต้องการเคอร์เซอร์ แสดงว่าคุณไม่ได้ออกแบบฐานข้อมูลของคุณอย่างเหมาะสมตั้งแต่แรก - person BoltBait; 13.11.2008
comment
@BoltBait: โดยส่วนตัวแล้วฉันคิดว่าถ้าคุณยืนยันแบบนั้นคุณจะอายุ 45 ไม่ได้จริงๆ :-P - person Steven A. Lowe; 14.11.2008
comment
เคอร์เซอร์ไม่ได้ช้าขนาดนั้นใน Oracle ซึ่งคุณสามารถใช้ส่วนคำสั่งเช่น BULK-COLLECT สำหรับโค้ดที่เน้นประสิทธิภาพได้ คงจะดีถ้าทำเกณฑ์มาตรฐาน - person Camilo Díaz Repka; 14.11.2008
comment
@Steven: ใช่แล้ว ฉันแก่แล้ว... และดื้อรั้นมาก! - person BoltBait; 17.11.2008
comment
@BoltBait: เด็กๆ ออกไปจากสนามหญ้าของฉันแล้ว! - person Steven A. Lowe; 20.11.2008
comment
ฉันคิดว่าเป็นคำพูดของ Edwin Dijkstra: การปรับให้เหมาะสมก่อนเวลาอันควรเป็นรากฐานของความชั่วร้ายทั้งหมด... ดังนั้นบางครั้งฉันก็คิดที่จะโต้แย้งเรื่องประสิทธิภาพ ใช้ชุดที่ควรใช้ชุดทั้งในเชิงตรรกะและทำให้อัลกอริทึมของคุณเข้าใจได้ แต่บางครั้งตรรกะทางธุรกิจอาจมีความชัดเจนมากขึ้นและปรับเปลี่ยนได้มากขึ้นเมื่อดำเนินการทีละแถว นั่นคือความคิดเห็นของฉันอย่างเห็นได้ชัด - person Paul; 14.02.2014
comment
@Paul: นั่นเป็นคำพูดของ Knuth และมันคือ Edgar Dijkstra แต่ฉันเห็นด้วยกับประโยคที่เหลือของคุณ :) - person Steven A. Lowe; 12.01.2016
comment
น่าตลกที่ฉันพบว่าตรรกะทางธุรกิจมักจะชัดเจนกว่าในโค้ดแบบตั้งค่า - person HLGEM; 21.08.2017

มีคำตอบด้านบนที่ระบุว่า "เคอร์เซอร์เป็นวิธีที่ช้าที่สุดในการเข้าถึงข้อมูลภายใน SQL Server ... เคอร์เซอร์ช้ากว่าทางเลือกอื่นที่ตั้งค่าไว้มากกว่าสามสิบเท่า"

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

ในกรณีที่ไม่มีกิจกรรมฐานข้อมูลอื่นๆ การดำเนินการตามการตั้งค่าจะเร็วขึ้นในระดับสากล ในระบบการผลิตก็ขึ้นอยู่กับ

person Community    schedule 13.11.2008
comment
ฟังดูเหมือนข้อยกเว้นที่พิสูจน์กฎ - person Joel Coehoorn; 13.11.2008
comment
@[Joel Coehoorn]: ฉันไม่เคยเข้าใจคำพูดนั้นเลย - person Steven A. Lowe; 13.11.2008
comment
@[Steven A. Lowe] phrases.org.uk /meanings/Exception-that-proves-the-rule.html เข้าใจข้อยกเว้นว่าเป็นสิ่งที่ถูกละเลย และโปรดทราบว่ากฎที่นี่เป็นสิ่งที่เหมือนกับเคอร์เซอร์ในสถานการณ์ส่วนใหญ่ที่ไม่ดี - person David Lay; 13.11.2008
comment
@delm: ขอบคุณสำหรับลิงก์ ตอนนี้ฉันเข้าใจวลีนี้น้อยลงแล้ว! - person Steven A. Lowe; 13.11.2008
comment
@[Steven A. Lowe] โดยพื้นฐานแล้วมันบอกว่าถ้าคุณฝ่าฝืนกฎด้วยตัวพิมพ์ย่อย จะต้องมีกฎทั่วไปที่จะฝ่าฝืน ดังนั้นจึงมีกฎอยู่ เช่น. จากลิงก์: (หากเรามีข้อความเช่น 'เข้าชมฟรีในวันอาทิตย์' เราก็สามารถสันนิษฐานได้ว่า ตามกฎทั่วไปแล้ว จะมีการเรียกเก็บเงินค่าเข้าชม) - person Fry; 13.11.2008
comment
@Fry: โอเค มันสมเหตุสมผลแล้ว - แล้วมันจะมีผลอย่างไรที่นี่? - person Steven A. Lowe; 13.11.2008
comment
ฉันคิดว่าเขาบอกว่าเมื่อมีปัญหาในการล็อค / หน่วยความจำจำกัดให้ใช้เคอร์เซอร์ นี่ก็หมายความว่าคุณไม่ควรใช้เคอร์เซอร์เป็นอย่างอื่น - person SapphireSun; 27.02.2010
comment
อีกตัวอย่างหนึ่งของการใช้เคอร์เซอร์ที่เหมาะสม: support.microsoft.com/kb/973849 เวอร์ชันดั้งเดิมใช้เทคนิคแบบกำหนดไว้และมีปัญหาในการล็อค - person Moe Sisko; 02.07.2013
comment
และที่น่าสนใจคือ ประเภทของชุดข้อมูลที่พวกเขากำลังพูดถึง (ข้อมูลสถานะเซสชันจากเว็บแอปพลิเคชัน) ตรงตามเกณฑ์ที่ฉันกล่าวถึงในโพสต์ต้นฉบับทุกประการ ซึ่งเป็นชุดข้อมูลที่หลายแถวได้รับผลกระทบจากการดำเนินการ แต่ตัวตารางเอง ได้รับการอ่านการผลิตอย่างต่อเนื่อง เวอร์ชันดั้งเดิมของสิ่งนี้คงจะตายสำหรับไซต์ที่มีปริมาณการเข้าชมจำนวนมาก - person davidcl; 16.07.2013

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

หนังสือ SQL ที่ร้ายแรงที่สุดมีบทที่ห้ามใช้เคอร์เซอร์ สิ่งที่เขียนอย่างดีทำให้ชัดเจนว่าเคอร์เซอร์มีตำแหน่ง แต่ไม่ควรใช้สำหรับการดำเนินการตามการตั้งค่า

มีบางสถานการณ์ที่เคอร์เซอร์เป็นตัวเลือกที่ถูกต้อง หรืออย่างน้อยก็เป็นทางเลือกที่ถูกต้อง

person Community    schedule 13.11.2008

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

person Community    schedule 13.11.2008

ใน Oracle PL/SQL เคอร์เซอร์จะไม่ส่งผลให้ตารางถูกล็อค และคุณสามารถใช้การเก็บรวบรวม/การดึงข้อมูลจำนวนมากได้

ใน Oracle 10 เคอร์เซอร์โดยนัยที่ใช้บ่อย

  for x in (select ....) loop
    --do something 
  end loop;

ดึงข้อมูลครั้งละ 100 แถวโดยปริยาย การรวบรวมจำนวนมาก/การดึงข้อมูลจำนวนมากอย่างชัดเจนก็เป็นไปได้เช่นกัน

อย่างไรก็ตาม เคอร์เซอร์ PL/SQL เป็นทางเลือกสุดท้าย ให้ใช้เคอร์เซอร์เหล่านี้เมื่อคุณไม่สามารถแก้ปัญหาด้วย SQL แบบ set-based ได้

อีกเหตุผลหนึ่งคือการทำให้ขนานกัน มันง่ายกว่าสำหรับฐานข้อมูลในการทำให้คำสั่งตามชุดใหญ่ขนานกันมากกว่าโค้ดที่จำเป็นแบบแถวต่อแถว นี่เป็นเหตุผลเดียวกับว่าทำไมการเขียนโปรแกรมเชิงฟังก์ชันจึงได้รับความนิยมมากขึ้นเรื่อยๆ (Haskell, F#, Lisp, C# LINQ, MapReduce ...) การเขียนโปรแกรมเชิงฟังก์ชันทำให้การทำงานแบบขนานง่ายขึ้น จำนวน CPU ต่อคอมพิวเตอร์เพิ่มขึ้น ดังนั้นการทำงานแบบขนานจึงกลายเป็นปัญหามากขึ้นเรื่อยๆ

person Community    schedule 10.01.2009

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

person Community    schedule 13.11.2008
comment
คุณมีเกณฑ์มาตรฐานหรือข้อมูลอ้างอิงสำหรับสิ่งนี้หรือไม่? ฉันไม่ได้สังเกตเห็นประสิทธิภาพการทำงานที่ลดลงอย่างมากเช่นนี้ ... แต่บางทีตารางของฉันอาจมีแถวไม่เพียงพอที่จะมีความสำคัญ (ปกติหนึ่งล้านหรือน้อยกว่านั้น) - person Steven A. Lowe; 13.11.2008
comment
โอ้ เดี๋ยวก่อน ฉันเห็นสิ่งที่คุณหมายถึง - แต่ฉันจะไม่สนับสนุนการใช้เคอร์เซอร์แทนการดำเนินการที่ตั้งไว้ เพียงแต่จะไม่สุดขั้วเพื่อหลีกเลี่ยงเคอร์เซอร์ - person Steven A. Lowe; 13.11.2008
comment
ฉันจำครั้งแรกที่ฉันทำ SQL ได้ เราต้องนำเข้าไฟล์ข้อมูลรายวันขนาด 50,000 ไฟล์จากเมนเฟรมไปยังฐานข้อมูล SQL Server... ฉันใช้เคอร์เซอร์และพบว่าการนำเข้าใช้เวลาประมาณ 26 ชั่วโมงโดยใช้เคอร์เซอร์.. เมื่อฉันเปลี่ยนเป็นการดำเนินการตามการตั้งค่า กระบวนการนี้ใช้เวลา 20 นาที - person Charles Bretana; 13.11.2008

คำตอบข้างต้นไม่ได้เน้นย้ำถึงความสำคัญของการล็อคมากพอ ฉันไม่ใช่แฟนตัวยงของเคอร์เซอร์เพราะมันมักจะส่งผลให้ระดับตารางล็อค

person Community    schedule 28.12.2008
comment
ใช่ขอบคุณ! หากไม่มีตัวเลือกในการป้องกัน (อ่านอย่างเดียว ส่งต่อเท่านั้น ฯลฯ) แน่นอนว่าการดำเนินการใด ๆ (เซิร์ฟเวอร์ sql) ที่ดำเนินการจะครอบครองหลายแถวและหลายหน้าของแถว - person Steven A. Lowe; 29.12.2008
comment
?? นั่นเป็นปัญหากับกลยุทธ์การล็อคของคุณไม่ใช่เคอร์เซอร์ แม้แต่คำสั่ง SELECT ก็เพิ่มการล็อคการอ่าน - person Adam; 13.03.2019

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

person Community    schedule 14.11.2008
comment
หากคุณหมายถึงการรันการรวมบางประเภท (ต่ำสุด สูงสุด ผลรวม) DBMS ที่มีความสามารถใดๆ จะเอาชนะกางเกงในฝั่งไคลเอ็นต์ โซลูชันที่ใช้เคอร์เซอร์ หากเพียงเพราะฟังก์ชันทำงานในเอ็นจิ้นและไม่มี ลูกค้า ‹--› โอเวอร์เฮดเซิร์ฟเวอร์ บางที SQL Server อาจไม่มีความสามารถใช่ไหม - person Richard T; 28.12.2008
comment
@[Richard T]: เรากำลังพูดถึงเคอร์เซอร์ฝั่งเซิร์ฟเวอร์ เนื่องจากอยู่ในขั้นตอนการจัดเก็บ ไม่ใช่เคอร์เซอร์ฝั่งไคลเอ็นต์ ขอโทษสำหรับความสับสน! - person Steven A. Lowe; 29.12.2008

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

person Community    schedule 09.06.2009
comment
SQL เป็นเรื่องยากที่จะดีบัก แม้ว่าจะไม่มีเคอร์เซอร์ก็ตาม เครื่องมือขั้นตอนผ่าน MS SQL ใน Visual Studio ดูเหมือนจะไม่ชอบฉัน (พวกมันค้างมากหรือไม่สะดุดเบรกพอยต์เลย) ดังนั้นฉันจึงมักจะลดลงเหลือคำสั่ง PRINT ;-) - person Steven A. Lowe; 10.06.2009

คุณสามารถโพสต์ตัวอย่างเคอร์เซอร์นั้นหรือลิงก์ไปยังคำถามได้หรือไม่ อาจมีวิธีที่ดีกว่า CTE แบบเรียกซ้ำ

นอกเหนือจากความคิดเห็นอื่นๆ แล้ว เคอร์เซอร์เมื่อใช้อย่างไม่เหมาะสม (ซึ่งบ่อยครั้ง) จะทำให้เกิดการล็อกหน้า/แถวโดยไม่จำเป็น

person Community    schedule 13.11.2008
comment
มีวิธีที่ดีกว่า - เคอร์เซอร์ประหลาด ;-) - person Steven A. Lowe; 13.11.2008

คุณอาจสรุปคำถามของคุณหลังจากย่อหน้าที่สอง แทนที่จะเรียกคนอื่นว่า "บ้า" เพียงเพราะพวกเขามีมุมมองที่แตกต่างจากคุณ และพยายามเยาะเย้ยผู้เชี่ยวชาญที่อาจมีเหตุผลที่ดีในการรู้สึกแบบที่พวกเขาทำ

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

person Community    schedule 13.11.2008
comment
โปรดอ่านอย่างละเอียดมากขึ้น ทอม - วลีที่แน่นอนคือความเกลียดชังอย่างบ้าคลั่ง เกลียดชังเป็นเป้าหมายของคำคุณศัพท์บ้า ไม่ใช่คน ภาษาอังกฤษอาจจะยากสักหน่อยในบางครั้ง ;-) - person Steven A. Lowe; 13.11.2008

โดยพื้นฐานแล้วโค้ด 2 บล็อกที่ทำสิ่งเดียวกัน อาจเป็นตัวอย่างที่แปลกนิดหน่อย แต่ก็พิสูจน์ประเด็นนี้ได้ เซิร์ฟเวอร์ SQL 2005:

SELECT * INTO #temp FROM master..spt_values
DECLARE @startTime DATETIME

BEGIN TRAN 

SELECT @startTime = GETDATE()
UPDATE #temp
SET number = 0
select DATEDIFF(ms, @startTime, GETDATE())

ROLLBACK 

BEGIN TRAN 
DECLARE @name VARCHAR

DECLARE tempCursor CURSOR
    FOR SELECT name FROM #temp

OPEN tempCursor

FETCH NEXT FROM tempCursor 
INTO @name

SELECT @startTime = GETDATE()
WHILE @@FETCH_STATUS = 0
BEGIN

    UPDATE #temp SET number = 0 WHERE NAME = @name
    FETCH NEXT FROM tempCursor 
    INTO @name

END 
select DATEDIFF(ms, @startTime, GETDATE())
CLOSE tempCursor
DEALLOCATE tempCursor

ROLLBACK 
DROP TABLE #temp

การอัปเดตครั้งเดียวใช้เวลา 156 มิลลิวินาที ในขณะที่เคอร์เซอร์ใช้เวลา 2016 มิลลิวินาที

person Community    schedule 13.11.2008
comment
ใช่ มันพิสูจน์ได้ว่านี่เป็นวิธีที่โง่มากในการใช้เคอร์เซอร์! แต่จะเกิดอะไรขึ้นถ้าการอัพเดตแต่ละแถวขึ้นอยู่กับค่าของแถวก่อนหน้าตามลำดับวันที่? - person Steven A. Lowe; 13.11.2008
comment
เริ่มต้นทรานส์ เลือกเบสวาล 1 อันดับแรกจากตาราง เรียงตามการประทับเวลา DESC INSERT ตาราง (ฟิลด์) ค่า (วาลรวมถึงค่าที่ได้มาจากบันทึกก่อนหน้า) คอมมิตทราน - person dkretz; 13.11.2008
comment
@doofledorfer: ที่จะแทรกหนึ่งแถวตามแถวสุดท้ายตามวันที่ ไม่อัปเดตทุกแถวด้วยค่าจากแถวก่อนหน้าตามลำดับวันที่ - person Steven A. Lowe; 14.11.2008
comment
หากต้องการใช้เคอร์เซอร์อย่างแท้จริง คุณควรใช้ WHERE CURRENT OF ในการอัพเดต - person erikkallen; 28.12.2008