ขั้นตอนการจัดเก็บเทียบกับแบบอินไลน์ SQL


27

ฉันรู้ว่าขั้นตอนการจัดเก็บมีประสิทธิภาพมากขึ้นผ่านเส้นทางการดำเนินการ (กว่า inline sql ในแอปพลิเคชัน) อย่างไรก็ตามเมื่อกดฉันไม่ได้รู้เรื่องทำไม

ฉันต้องการทราบเหตุผลทางเทคนิคสำหรับเรื่องนี้ (ในแบบที่ฉันสามารถอธิบายให้ใครบางคนในภายหลัง)

ใครสามารถช่วยฉันสร้างคำตอบที่ดีได้บ้าง


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

@marc_s นั้นเป็นจริงหากข้อความค้นหาตรงกัน อย่างไรก็ตามในขณะที่ฉันชี้ให้เห็นในคำตอบของฉันมีลักษณะบางอย่างของคำสั่งเฉพาะกิจที่อาจมีปัญหาด้านประสิทธิภาพแม้กระทั่งคำถามที่ดูเหมือนกัน
Aaron Bertrand

คำตอบ:


42

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

ฉันยังคงต้องการวิธีการจัดเก็บจากด้าน DBA ด้วยเหตุผลดังต่อไปนี้ (และหลายวิธีอาจมีผลกระทบอย่างมากต่อประสิทธิภาพ)

  • หากฉันมีหลายแอพที่ใช้การค้นหาเดียวกันซ้ำอีกครั้งโพรซีเดอร์ที่เก็บจะห่อหุ้มลอจิกนั้นแทนที่จะกำจัดการเคียวรีเฉพาะกิจแบบเดียวกันหลายครั้งในโคเด็ตโค้ดที่ต่างกัน แอปพลิเคชันที่ใช้คิวรีเดิมซ้ำยังสามารถอยู่ในการวางแผนการขยายตัวของแคชเว้นแต่ว่าพวกเขาจะถูกคัดลอกคำต่อคำ แม้ความแตกต่างในกรณีและพื้นที่สีขาวสามารถนำไปสู่การจัดเก็บแผนเดียวกันหลายรุ่น (สิ้นเปลือง)
  • ฉันสามารถตรวจสอบและแก้ไขสิ่งที่แบบสอบถามกำลังทำอยู่โดยไม่ต้องเข้าถึงซอร์สโค้ดของแอปพลิเคชันหรือเรียกใช้การติดตามที่มีราคาแพงเพื่อดูว่าแอปพลิเคชันกำลังทำอะไรอยู่
  • ฉันยังสามารถควบคุม (และรู้ล่วงหน้า) ว่าแบบสอบถามใดบ้างที่แอปพลิเคชันสามารถเรียกใช้ตารางใดที่สามารถเข้าถึงและในบริบทใดเป็นต้นหากนักพัฒนากำลังเขียนคิวรีแบบเฉพาะกิจในแอปพลิเคชันของพวกเขา ดึงแขนเสื้อของฉันทุกครั้งที่พวกเขาต้องการเข้าถึงตารางที่ฉันไม่รู้หรือไม่สามารถคาดเดาได้หรือถ้าฉันไม่รับผิดชอบ / กระตือรือร้นและ / หรือใส่ใจเรื่องความปลอดภัยฉันก็จะโปรโมตนั้น ผู้ใช้ไปยัง dbo ดังนั้นพวกเขาจึงหยุดดักฟังฉัน โดยทั่วไปแล้วจะทำเมื่อนักพัฒนามีจำนวนมากกว่า DBA หรือ DBA ที่ดื้อรั้น ประเด็นสุดท้ายนั่นคือสิ่งที่ไม่ดีของเราและเราจำเป็นต้องดีขึ้นเกี่ยวกับการให้แบบสอบถามที่คุณต้องการ
  • ในบันทึกที่เกี่ยวข้องชุดของขั้นตอนการจัดเก็บเป็นวิธีที่ง่ายมากในการตรวจสอบรายการที่อาจใช้คำสั่งบนระบบของฉัน ทันทีที่แอปพลิเคชันได้รับอนุญาตให้ข้ามขั้นตอนและส่งแบบสอบถามเฉพาะกิจเพื่อค้นหาพวกเขาฉันต้องเรียกใช้การติดตามที่ครอบคลุมวงจรธุรกิจทั้งหมดหรือแยกวิเคราะห์รหัสแอปพลิเคชันทั้งหมด (อีกครั้งว่า ฉันอาจไม่สามารถเข้าถึง) เพื่อค้นหาสิ่งที่ดูเหมือนแบบสอบถาม ความสามารถในการดูรายการของกระบวนงานที่เก็บไว้ (และ grep เป็นแหล่งเดียวsys.sql_modulesสำหรับการอ้างอิงไปยังวัตถุเฉพาะ) ทำให้ชีวิตของทุกคนง่ายขึ้นมาก
  • ฉันสามารถเพิ่มความยาวได้มากขึ้นเพื่อป้องกันการฉีด SQL แม้ว่าฉันจะรับอินพุตและดำเนินการกับ SQL แบบไดนามิกฉันสามารถควบคุมสิ่งที่ได้รับอนุญาตให้เกิดขึ้นมากมาย ฉันไม่สามารถควบคุมสิ่งที่นักพัฒนาทำเมื่อสร้างคำสั่ง inline SQL
  • ฉันสามารถเพิ่มประสิทธิภาพการสืบค้น (หรือการสืบค้น) โดยไม่ต้องเข้าถึงซอร์สโค้ดของแอปพลิเคชันความสามารถในการเปลี่ยนแปลงความรู้เกี่ยวกับภาษาแอปพลิเคชันให้ทำได้อย่างมีประสิทธิภาพอำนาจ (ไม่ต้องกังวลกับการรบกวน) แอพ ฯลฯ ปัญหานี้เป็นปัญหาอย่างยิ่งหากมีการเผยแพร่แอพ
  • ฉันสามารถบังคับให้ตัวเลือกการตั้งค่าบางอย่างภายในกระบวนงานที่เก็บไว้เพื่อหลีกเลี่ยงการค้นหาแต่ละข้อจากการอยู่ภายใต้การช้าในแอปพลิเคชันรวดเร็วใน SSMS หรือไม่ ปัญหาที่เกิดขึ้น หมายความว่าสำหรับสองแอปพลิเคชันที่แตกต่างกันซึ่งเรียกว่าคิวรีแบบเฉพาะกิจจะมีSET ANSI_WARNINGS ONและอีกแอพหนึ่งมีSET ANSI_WARNINGS OFFและพวกเขาจะมีสำเนาแผนของตัวเอง แผนการที่พวกเขาได้รับนั้นขึ้นอยู่กับพารามิเตอร์ที่ใช้สถิติในสถานที่ ฯลฯ ครั้งแรกที่มีการเรียกใช้แบบสอบถามในแต่ละกรณีซึ่งอาจนำไปสู่แผนการที่แตกต่างกันและด้วยเหตุนี้ประสิทธิภาพที่แตกต่างกันมาก
  • ฉันสามารถควบคุมสิ่งต่าง ๆ เช่นชนิดข้อมูลและวิธีการใช้พารามิเตอร์ต่างจาก ORM บางอย่าง - บางรุ่นก่อนหน้าของสิ่งต่าง ๆ เช่น EF จะกำหนดพารามิเตอร์การสืบค้นตามความยาวของพารามิเตอร์ดังนั้นหากฉันมีพารามิเตอร์ N'Smith 'และ N' อื่น จอห์นสัน 'ฉันจะได้รับแผนสองรุ่นที่แตกต่างกัน พวกเขาได้แก้ไขสิ่งนี้แล้ว พวกเขาแก้ไขปัญหานี้แล้ว แต่ยังมีอะไรอีกบ้างที่แตกหัก
  • ฉันสามารถทำสิ่งต่าง ๆ ที่ ORMs และกรอบงานและห้องสมุด "ที่เป็นประโยชน์" อื่น ๆ ยังไม่สามารถให้การสนับสนุนได้

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


2
อีกเหตุผลหนึ่งสำหรับขั้นตอนการจัดเก็บ? สำหรับข้อความค้นหาที่ซับซ้อนและยาวคุณจะต้องส่งข้อความค้นหาไปยังเซิร์ฟเวอร์ทุกครั้งเว้นแต่จะเป็น sproc จากนั้นคุณเพียงกด "exec sprocname" และพารามิเตอร์บางตัว สิ่งนี้อาจสร้างความแตกต่างบนเครือข่ายที่ช้า (หรือไม่ว่าง)
David Crowell

0

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

คำแนะนำใด ๆ ที่มอบให้กับนักพัฒนาที่สนับสนุนการใช้ข้อความ SQL ดิบจะต้องเต็มไปด้วยคำเตือนมากมายเช่นที่ฉันคิดว่าคำแนะนำที่รอบคอบที่สุดคือการส่งเสริมการใช้วิธีการจัดเก็บอย่างมากและกีดกันทีมนักพัฒนาของคุณจากการฝึกปฏิบัติ ของการฝังคำสั่ง SQL ในรหัสหรือการส่งคำขอ SQL แบบข้อความธรรมดาที่ไม่ใช่แบบดั้งเดิมนอก SQL SPROC (ขั้นตอนการจัดเก็บ)

ฉันคิดว่าคำตอบง่ายๆสำหรับคำถามที่ว่าทำไมการใช้ SPROC จึงเป็นเหมือนผู้ส่งที่คาดเดา: SPROC จะได้รับการแยกวิเคราะห์ปรับให้เหมาะสมและเรียบเรียง ดังนั้นแผนแบบสอบถาม / การดำเนินการของพวกเขาจะถูกเก็บไว้เพราะคุณได้บันทึกการเป็นตัวแทนของแบบสอบถามและคุณโดยทั่วไปจะแตกต่างกันไปตามพารามิเตอร์เท่านั้นซึ่งไม่เป็นความจริงในกรณีของคำสั่ง SQL ที่คัดลอก / วางซึ่งอาจ morph จากหน้าต่อหน้าและส่วนประกอบ / ระดับและมักจะแปรปรวนในขอบเขตที่ตารางที่แตกต่างกันแม้ชื่อฐานข้อมูลสามารถระบุได้จากการโทรเพื่อโทร การอนุญาตเฉพาะกิจแบบนี้การส่ง SQL ช่วยลดโอกาสที่ DB Engine จะใช้แผนคิวรีสำหรับคำสั่งเฉพาะกิจของคุณอีกครั้งตามกฎที่เข้มงวดมาก ที่นี่ฉันกำลังสร้างความแตกต่างระหว่างแบบสอบถามเฉพาะกิจแบบไดนามิก (ในจิตวิญญาณของคำถามขึ้น) กับการใช้ระบบที่มีประสิทธิภาพ SPROC sp_executesql

โดยเฉพาะอย่างยิ่งมีองค์ประกอบดังต่อไปนี้:

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

เมื่อคำสั่ง SQL ออกจากหน้าเว็บเรียกว่า "คำสั่ง ad hoc" เอ็นจิ้นจะค้นหาแผนการดำเนินการที่มีอยู่เพื่อจัดการกับคำขอ เนื่องจากนี่คือข้อความที่ส่งมาจากผู้ใช้จึงจะถูกนำเข้าไปวิเคราะห์แยกวิเคราะห์และประมวลผลหากมันถูกต้อง ในเวลานี้จะได้รับค่าใช้จ่ายแบบสอบถามเป็นศูนย์ ค่าใช้จ่ายแบบสอบถามจะใช้เมื่อเอ็นจิน DB ใช้อัลกอริธึมเพื่อกำหนดว่าแผนปฏิบัติการใดที่จะขับไล่จากแคช

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

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

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

ดังนั้นจึงค่อนข้างเป็นไปได้ที่แผนดังกล่าวจะถูกขับไล่ก่อนเมื่อเกิดความกดดันจากหน่วยความจำ

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

ตอนนี้ถ้าฉันไม่ถูกต้องจริงเกี่ยวกับหนึ่งหรือหลายจุดฉันแน่นอนเปิดให้แก้ไข

สุดท้ายผู้เขียนเขียนว่า:

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

ฉันเชื่อว่าผู้เขียนอ้างถึงตัวเลือก "เพิ่มประสิทธิภาพสำหรับปริมาณงานเฉพาะกิจ"

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

อย่างไรก็ตามคุณต้องเปิดตัวเลือกนี้เนื่องจากจะปิดไว้ตามค่าเริ่มต้น

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

สำหรับข้อมูลเพิ่มเติมโปรดดู:

https://technet.microsoft.com/en-us/library/ms181055(v=sql.105).aspx
http://sqlmag.com/database-performance-tuning/don-t-fear-dynamic-sql

ดีที่สุด
เฮนรี่


4
ฉันอ่านบทความของคุณหลายย่อหน้าอย่างระมัดระวังสองหรือสามครั้งและฉันก็ยังไม่รู้ว่าคุณกำลังคิดจะสื่อความคิดอะไร ในบางกรณีคุณปรากฏในตอนท้ายของประโยคว่าตรงข้ามกับสิ่งที่ประโยคเริ่มพยายามที่จะพูด คุณจำเป็นต้องพิสูจน์อักษรและแก้ไขการส่งนี้อย่างระมัดระวัง
Pieter Geerkens

ขอบคุณสำหรับข้อเสนอแนะปีเตอร์ หากเป็นกรณีนี้เป็นไปได้ที่ฉันควรย่อประโยคของฉันให้สั้นลงเพื่อให้ชัดเจนยิ่งขึ้น คุณช่วยยกตัวอย่างที่ฉันปรากฏว่าตรงข้ามกับความคิดเดิมได้หรือไม่? ชื่นชมมาก
Henry

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

1
ดูเหมือนว่าการรังเกียจที่จะ "ad hoc" sql นั้นขึ้นอยู่กับแนวคิดที่ว่า sql นั้นเปลี่ยนแปลงไประหว่างการประหารชีวิต ... นี่เป็นเรื่องจริงทั้งหมดเมื่อมีการเกี่ยวข้องกับการกำหนดพารามิเตอร์
b_levitt

0

TLDR: ไม่มีความแตกต่างของประสิทธิภาพที่เห็นได้ระหว่างสองตราบเท่าที่อินไลน์ sql ของคุณได้รับการกำหนดพารามิเตอร์

นี่คือเหตุผลที่ฉันค่อยๆยกเลิกขั้นตอนการจัดเก็บ:

  • เราใช้สภาพแวดล้อมแอปพลิเคชัน 'เบต้า' - สภาพแวดล้อมแบบขนานกับการผลิตที่ใช้ฐานข้อมูลการผลิตร่วมกัน เนื่องจากรหัส db อยู่ในระดับแอปพลิเคชันและการเปลี่ยนแปลงโครงสร้าง db นั้นหาได้ยากเราสามารถอนุญาตให้ผู้ใช้ยืนยันการทำงานใหม่นอกเหนือจาก QA และทำการปรับใช้นอกหน้าต่างการปรับใช้การผลิต แต่ยังมีฟังก์ชันการผลิตและการแก้ไขที่ไม่สำคัญ สิ่งนี้จะเป็นไปไม่ได้หากครึ่งหนึ่งของรหัสแอปพลิเคชันอยู่ในฐานข้อมูล

  • เราฝึกฝนผู้พัฒนาอุปกรณ์ในระดับฐานข้อมูล (octopus + dacpacs) อย่างไรก็ตามในขณะที่ชั้นธุรกิจขึ้นไปสามารถล้างและแทนที่และกู้คืนได้เพียงแค่ย้อนกลับ แต่ก็ไม่เป็นความจริงสำหรับการเปลี่ยนแปลงที่เพิ่มขึ้นและอาจเป็นอันตรายซึ่งต้องไปที่ฐานข้อมูล ดังนั้นเราต้องการให้การปรับใช้ฐานข้อมูลของเราเบาลงและบ่อยขึ้น

  • เพื่อหลีกเลี่ยงสำเนาที่ใกล้เคียงกันของรหัสเดียวกันสำหรับพารามิเตอร์ทางเลือกเรามักจะใช้รูปแบบ 'โดยที่ @var เป็นโมฆะหรือ @ var = table.field' ด้วย proc ที่จัดเก็บคุณมีแนวโน้มที่จะได้รับแผนการดำเนินการเดียวกันแม้จะมีความต้องการที่แตกต่างกันและทำให้เกิดปัญหาประสิทธิภาพการทำงานหรือกำจัดแผนการแคชด้วยคำแนะนำ 'recompile' อย่างไรก็ตามด้วยโค้ดที่เรียบง่ายซึ่งต่อท้ายความคิดเห็น "ลายเซ็น" ที่ส่วนท้ายของ sql เราสามารถบังคับใช้แผนที่แตกต่างกันโดยขึ้นอยู่กับว่าตัวแปรใดเป็นโมฆะ (ไม่สามารถตีความได้ว่าเป็นแผนที่แตกต่างกัน ไม่เป็นโมฆะ).

  • ฉันสามารถเปลี่ยนแปลงผลลัพธ์ได้อย่างน่าทึ่งด้วยการเปลี่ยนแปลงเล็กน้อยเพียงเล็กน้อยในทันทีไปยัง SQL ตัวอย่างเช่นฉันสามารถมีคำสั่งที่ปิดด้วย CTE สองรายการคือ "Raw" และ "ReportReady" ไม่มีอะไรที่บอกว่าต้องใช้ CTE ทั้งสองคำสั่ง sql ของฉันสามารถเป็นได้:

    ...

    เลือก * จาก {(รูปแบบ)} "

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

  • เมื่อคุณมีกฎ "procs เท่านั้น" คุณจะพบกับความซ้ำซ้อนมากมายใน sql ส่วนใหญ่ซึ่งกลายเป็น CRUD - คุณผูกพารามิเตอร์ทั้งหมดคุณจะแสดงรายการพารามิเตอร์เหล่านั้นทั้งหมดในลายเซ็น proc (และตอนนี้ คุณอยู่ในไฟล์ที่แตกต่างกันในโครงการอื่น) คุณจับคู่พารามิเตอร์อย่างง่ายเหล่านั้นกับคอลัมน์ของพวกเขา สิ่งนี้สร้างประสบการณ์การพัฒนาที่ไม่ปะติดปะต่อ

มีเหตุผลที่ถูกต้องในการใช้ procs:

  • ความปลอดภัย - คุณมีเลเยอร์อื่นที่นี่ที่แอพต้องผ่าน หากบัญชีบริการแอปพลิเคชันไม่ได้รับอนุญาตให้สัมผัสกับตาราง แต่มีสิทธิ์ "ดำเนินการ" ใน procs เท่านั้นคุณจะได้รับการคุ้มครองเป็นพิเศษ สิ่งนี้ไม่ได้ทำให้ได้รับเนื่องจากมีต้นทุน แต่เป็นไปได้

  • การนำกลับมาใช้ใหม่ - ในขณะที่ฉันจะบอกว่าการนำมาใช้ซ้ำส่วนใหญ่จะเกิดขึ้นที่ชั้นธุรกิจเพื่อให้แน่ใจว่าคุณไม่ได้ผ่านกฎเกณฑ์ทางธุรกิจที่ไม่เกี่ยวข้องกับฐานข้อมูลเรายังคงมี procs และฟังก์ชั่น

มีข้อโต้แย้งบางอย่างที่ไม่สนับสนุน procs หรือลด IMO ได้ง่าย:

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

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

  • ขนาดของรายงาน - คำสั่ง sql เพิ่มเติมของชื่อ proc โดยทั่วไปจะไม่สำคัญเมื่อเทียบกับข้อมูลที่กลับมา ถ้ามันใช้ได้สำหรับเอนทิตีมันก็โอเคสำหรับฉัน

  • การดูคิวรีที่ถูกต้องการสร้างคิวรีที่ง่ายต่อการค้นหาในรหัสนั้นง่ายพอ ๆ กับการเพิ่มตำแหน่งการโทรเป็นความคิดเห็นในโค้ด การคัดลอกโค้ดจาก c # code ไปยัง ssms ทำได้ง่ายเหมือนกับการแก้ไขความคิดสร้างสรรค์และการใช้ความคิดเห็น:

        //Usage /*{SSMSOnly_}*/Pure Sql To run in SSMS/*{_SSMSOnly}*/
        const string SSMSOnly_ = "*//*<SSMSOnly>/*";
        const string _SSMSOnly = "*/</SSMSOnly>";
        //Usage /*{NetOnly_}{InterpolationVariable}{_NetOnly}*/
        const string NetOnly_ = "*/";
        const string _NetOnly = "/*";
    
  • การฉีด sql - กำหนดพารามิเตอร์ข้อความค้นหาของคุณ เสร็จสิ้น นี่สามารถยกเลิกได้จริงถ้า proc นั้นใช้ dynamic sql แทน

  • การบายพาสการปรับใช้ - เราฝึกซ้อมที่ระดับฐานข้อมูลด้วยเช่นกันดังนั้นนี่จึงไม่ใช่ตัวเลือกสำหรับเรา

  • "ช้าในแอปพลิเคชันรวดเร็วใน SSMS" - นี่เป็นปัญหาการแคชแผนซึ่งส่งผลกระทบต่อทั้งสองฝ่าย ตัวเลือกการตั้งค่าเพียงทำให้แผนใหม่ที่จะรวบรวมที่ปรากฏขึ้นเพื่อแก้ไขปัญหาสำหรับตัวแปร ONE SET OFF นี่เป็นเพียงคำตอบว่าทำไมคุณถึงเห็นผลลัพธ์ที่แตกต่างกัน - ตัวเลือกการตั้งค่าเองไม่สามารถแก้ไขปัญหาการดมกลิ่นพารามิเตอร์

  • แผนการดำเนินการ sql แบบอินไลน์จะไม่ถูกแคช - เพียงแค่เท็จ คำสั่งที่กำหนดพารามิเตอร์เช่นเดียวกับชื่อ proc จะถูกแฮชอย่างรวดเร็วและจากนั้นจะมีการค้นหาแผนโดยแฮชนั้น มันเหมือนกัน 100%

  • เพื่อความชัดเจนฉันกำลังพูดถึง raw inline sql ไม่ได้สร้างรหัสจาก ORM - เราใช้ Dapper ซึ่งเป็น micro ORM ที่ดีที่สุด

https://weblogs.asp.net/fbouma/38178

/programming//a/15277/852208

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