sp_executesql รีเฟรชแผนแบบสอบถามเมื่อใด


13

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

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

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

ฉันอ่านสิ่งนี้ใน MSDN:

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

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

คำตอบ:


7

บรรทัดจาก MSDN กำลังพูดถึงการใช้EXEC()งานเช่นนี้:

SET @sql = 'SELECT foo FROM dbo.bar WHERE x = ''' + @x + ''';';
EXEC(@sql);

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

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

SET @sql = N'SELECT foo FROM dbo.bar WHERE x = @x;';
EXEC sp_executesql @sql, N'@x VARCHAR(32)', @x;

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

หากคุณกำลังมีปัญหาเกี่ยวกับแผนกลับมาใช้และ / หรือพารามิเตอร์ดมสิ่งบางอย่างที่คุณควรมีลักษณะเป็นอยู่OPTION (RECOMPILE), OPTIMIZE FOR, และoptimize for ad hoc workloads simple/forced parameterizationฉันตอบคำถามที่คล้ายกันสองสามข้อเพื่อตอบสนองต่อเว็บคาสต์เมื่อเร็ว ๆ นี้ที่นี่มันอาจจะคุ้มค่า

http://sqlperformance.com/performance-palooza

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


2

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


ขอบคุณสำหรับคำตอบของคุณฉันทำการแก้ไขเกี่ยวกับพารามิเตอร์ตามที่ฉันได้รับรู้ว่าทุกครั้งที่ฉันเรียก sp_ExecuteSql ฉันจะใช้สตริงที่แตกต่างกันเป็นแบบสอบถามเนื่องจากข้อเท็จจริงที่ว่าจากมุมมองของ SQL Server ฉันได้แทนที่ พารามิเตอร์ที่มีค่าฮาร์ดโค้ด (พวกเขาจะป้อนเป็นรหัสก่อนที่ฉันจะส่งแบบสอบถามของฉันไปยัง SQL Server) คุณรู้วิธีรอบนี้หรือไม่? การประกาศตัวแปรในคำสั่ง SQL ในบรรทัดของฉันจะช่วยให้เครื่องมือเพิ่มประสิทธิภาพคิวรีค้นหาแผนคิวรีที่แคชไว้หรือไม่
james lewis
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.