(คำถามย้ายจาก SO)
ฉันมีตาราง (ข้อมูลหุ่น) ที่มีดัชนีคลัสเตอร์ประกอบด้วย 2 คอลัมน์:
ตอนนี้ฉันเรียกใช้แบบสอบถามทั้งสองนี้:
declare
@productid int =1 ,
@priceid int = 1
SELECT productid,
t.priceID
FROM Transactions AS t
WHERE (productID = @productid OR @productid IS NULL)
AND (priceid = @priceid OR @priceid IS NULL)
SELECT productid,
t.priceID
FROM Transactions AS t
WHERE (productID = @productid)
AND (priceid = @priceid)
แผนปฏิบัติการจริงสำหรับทั้งคิวรีคือ:
อย่างที่คุณเห็นคนแรกใช้ SCAN ในขณะที่คนที่สองกำลังใช้ SEEK
อย่างไรก็ตาม - การเพิ่มOPTION (RECOMPILE)
ลงในแบบสอบถามแรกทำให้แผนการดำเนินการใช้ SEEK ด้วย:
เพื่อนที่แชท DBA บอกฉันว่า:
ในการสืบค้นของคุณ @ productid = 1 ซึ่งหมายความว่า (productID = @ productID หรือ @productID IS NULL) สามารถทำให้ง่ายขึ้น (productID = @ productID) อดีตต้องการสแกนเพื่อทำงานกับค่าใด ๆ ของ @productID ซึ่งหลังสามารถใช้การค้นหาได้ ดังนั้นเมื่อคุณใช้ RECOMPILE SQL Server จะดูว่าคุณมีค่าอะไรใน @productID และสร้างแผนการที่ดีที่สุด ด้วยค่าที่ไม่ใช่ค่า null ใน @productID การค้นหาดีที่สุด หากไม่ทราบค่าของ @productID แผนจะต้องมีค่าที่เป็นไปได้ใน @productID ซึ่งจะต้องมีการสแกน ถูกเตือน: OPTION (RECOMPILE) จะบังคับให้คอมไพล์ของแผนทุกครั้งที่คุณเรียกใช้ซึ่งจะเพิ่มมิลลิวินาทีสองสามครั้งในการดำเนินการทุกครั้ง แม้ว่านี่จะเป็นปัญหาหากแบบสอบถามทำงานบ่อยมาก
ยัง:
หาก @productID เป็นโมฆะคุณจะค้นหาว่ามูลค่าเท่าใด คำตอบ: ไม่มีอะไรให้ค้นหา ค่าทั้งหมดมีคุณสมบัติ
ฉันเข้าใจว่าOPTION (RECOMPILE)
กำลังบังคับให้ SQL Server เห็นค่าที่แท้จริงที่พารามิเตอร์มีและดูว่าสามารถดูได้หรือไม่
แต่ตอนนี้ฉันเสียประโยชน์จากการรวบรวมล่วงหน้า
คำถาม
IMHO - SCAN จะเกิดขึ้นเฉพาะเมื่อพารามิเตอร์เป็นโมฆะ
ไม่เป็นไร - ให้ SQL Server สร้างแผนการดำเนินการสำหรับ SCAN
แต่ถ้า SQL Server เห็นว่าฉันเรียกใช้แบบสอบถามนี้หลายครั้งด้วยค่า: 1,1
แล้วทำไมมันไม่สร้างแผนปฏิบัติการอีก ANEMER และใช้ SEEK สำหรับสิ่งนั้น?
AFAIK - SQL สร้างแผนการดำเนินการสำหรับเคียวรีที่พบบ่อยที่สุด
เหตุใด SQL Server จึงไม่บันทึกแผนการดำเนินการสำหรับ:
@productid int =1 , @priceid int = 1
(ฉันเรียกใช้หลาย ๆ ครั้งด้วยค่าเหล่านั้น)
- เป็นไปได้หรือไม่ที่จะบังคับให้ SQL รักษาแผนการดำเนินการนั้น (ซึ่งใช้ SEEK) - สำหรับการเรียกใช้ในอนาคต?