แบบสอบถามคือ
SELECT SUM(Amount) AS SummaryTotal
FROM PDetail WITH(NOLOCK)
WHERE ClientID = @merchid
AND PostedDate BETWEEN @datebegin AND @dateend
ตารางประกอบด้วยแถวที่ 103,129,000
แผนได้อย่างรวดเร็วมองขึ้นโดย ClientID กับกริยาที่เหลือในวัน แต่ต้องทำ 96 Amount
การค้นหาเพื่อดึง <ParameterList>
ส่วนในแผนมีดังนี้
<ParameterList>
<ColumnReference Column="@dateend"
ParameterRuntimeValue="'2013-02-01 23:59:00.000'" />
<ColumnReference Column="@datebegin"
ParameterRuntimeValue="'2013-01-01 00:00:00.000'" />
<ColumnReference Column="@merchid"
ParameterRuntimeValue="(78155)" />
</ParameterList>
แผนแบบช้าจะค้นหาตามวันที่และมีการค้นหาเพื่อประเมินเพรดิเคตที่เหลือบน ClientId และเพื่อดึงจำนวนเงิน (โดยประมาณ 1 เทียบกับจริง 7,388,383) <ParameterList>
ส่วนคือ
<ParameterList>
<ColumnReference Column="@EndDate"
ParameterCompiledValue="'2013-02-01 23:59:00.000'"
ParameterRuntimeValue="'2013-02-01 23:59:00.000'" />
<ColumnReference Column="@BeginDate"
ParameterCompiledValue="'2013-01-01 00:00:00.000'"
ParameterRuntimeValue="'2013-01-01 00:00:00.000'" />
<ColumnReference Column="@ClientID"
ParameterCompiledValue="(78155)"
ParameterRuntimeValue="(78155)" />
</ParameterList>
ในกรณีที่สองนี้ParameterCompiledValue
เป็นไม่ว่างเปล่า SQL Server ดมกลิ่นค่าที่ใช้ในแบบสอบถามสำเร็จแล้ว
หนังสือ"การแก้ไขปัญหาเบื้องต้นในทางปฏิบัติของ SQL Server 2005"มีไว้เพื่อกล่าวถึงการใช้ตัวแปรโลคอล
การใช้ตัวแปรท้องถิ่นเพื่อกำจัดการดมกลิ่นพารามิเตอร์เป็นเคล็ดลับที่ใช้กันโดยทั่วไป แต่คำใบ้OPTION (RECOMPILE)
และOPTION (OPTIMIZE FOR)
คำแนะนำ ... โดยทั่วไปแล้วจะสวยงามกว่าและมีความเสี่ยงน้อยกว่า
บันทึก
ใน SQL Server 2005 การคอมไพล์ระดับคำสั่งอนุญาตให้มีการคอมไพล์ของแต่ละคำสั่งในกระบวนงานที่เก็บไว้ที่จะรอการตัดบัญชีจนกระทั่งก่อนการดำเนินการของแบบสอบถามแรก จากนั้นค่าของตัวแปรท้องถิ่นจะเป็นที่รู้จัก ในทางทฤษฎี SQL Server สามารถใช้ประโยชน์จากสิ่งนี้ในการดมกลิ่นค่าตัวแปรท้องถิ่นในลักษณะเดียวกับที่มันดมพารามิเตอร์ อย่างไรก็ตามเนื่องจากเป็นเรื่องปกติที่จะใช้ตัวแปรโลคัลเพื่อกำจัดพารามิเตอร์การดมกลิ่นใน SQL Server 7.0 และ SQL Server 2000+ การดมกลิ่นของตัวแปรโลคัลไม่ได้เปิดใช้งานใน SQL Server 2005 มันอาจถูกเปิดใช้งานใน SQL Server รุ่นต่อไปในอนาคต เหตุผลที่ใช้หนึ่งในตัวเลือกอื่น ๆ ที่ระบุไว้ในบทนี้หากคุณมีตัวเลือก
จากการทดสอบอย่างรวดเร็วด้วยเหตุนี้พฤติกรรมที่อธิบายไว้ข้างต้นจะยังคงเหมือนเดิมในปี 2008 และ 2012 และตัวแปรจะไม่ถูกดักจับสำหรับการคอมไพล์ที่รอการตัดบัญชี แต่เฉพาะเมื่อมีการใช้OPTION RECOMPILE
คำใบ้อย่างชัดเจนเท่านั้น
DECLARE @N INT = 0
CREATE TABLE #T ( I INT );
/*Reference to #T means this statement is subject to deferred compile*/
SELECT *
FROM master..spt_values
WHERE number = @N
AND EXISTS(SELECT COUNT(*) FROM #T)
SELECT *
FROM master..spt_values
WHERE number = @N
OPTION (RECOMPILE)
DROP TABLE #T
แม้จะมีการคอมไพล์รอการตัดบัญชีตัวแปรจะไม่ถูกดมกลิ่นและจำนวนแถวโดยประมาณไม่ถูกต้อง
ดังนั้นฉันคิดว่าแผนช้าเกี่ยวข้องกับเวอร์ชันที่กำหนดพารามิเตอร์ของแบบสอบถาม
ParameterCompiledValue
เท่ากับParameterRuntimeValue
ทั้งหมดของพารามิเตอร์ดังนั้นนี้ไม่พารามิเตอร์ทั่วไปดม (ที่แผนถูกเรียบเรียงสำหรับหนึ่งชุดของค่าทำงานแล้วสำหรับชุดของค่าอื่น)
ปัญหาคือแผนการที่รวบรวมไว้สำหรับค่าพารามิเตอร์ที่ถูกต้องนั้นไม่เหมาะสม
คุณมีแนวโน้มที่จะตีปัญหากับจากน้อยไปมากวันที่อธิบายไว้ที่นี่และที่นี่ สำหรับตารางที่มี 100 ล้านแถวคุณต้องแทรก (หรือแก้ไขอย่างอื่น) 20 ล้านแถวก่อนที่ SQL Server จะอัปเดตสถิติให้คุณโดยอัตโนมัติ ดูเหมือนว่าครั้งล่าสุดที่พวกเขาได้รับการปรับปรุงแถวศูนย์ตรงกับช่วงวันที่ในแบบสอบถาม แต่ตอนนี้ 7 ล้านทำ
คุณสามารถกำหนดเวลาการอัปเดตสถิติบ่อยครั้งมากขึ้นพิจารณาการตั้งค่าสถานะการติดตาม2389 - 90
หรือการใช้OPTIMIZE FOR UKNOWN
ดังนั้นเพียงแค่ย้อนกลับไปคาดเดาแทนที่จะสามารถใช้สถิติที่ทำให้เข้าใจผิดในปัจจุบันในdatetime
คอลัมน์
สิ่งนี้อาจไม่จำเป็นใน SQL Server เวอร์ชันถัดไป (หลังปี 2012) รายการ Connect ที่เกี่ยวข้องมีการตอบสนองที่น่าสนใจ
โพสต์โดย Microsoft เมื่อ 8/28/2012 เวลา 13:35 น.
เราได้ทำการปรับปรุงการประมาณค่า cardinality สำหรับการเปิดตัวครั้งสำคัญครั้งต่อไปที่จะแก้ไขสิ่งนี้ คอยติดตามรายละเอียดเมื่อภาพตัวอย่างของเราออกมา เอริค
การปรับปรุงในปี 2014 นี้ถูกมองโดย Benjamin Nevarez ในตอนท้ายของบทความ:
ดูครั้งแรกที่นิว SQL Server Cardinality ประมาณการ
ดูเหมือนว่าตัวประมาณค่า cardinality ใหม่จะถอยกลับและใช้ความหนาแน่นเฉลี่ยในกรณีนี้แทนที่จะให้ค่าประมาณ 1 แถว
รายละเอียดเพิ่มเติมเกี่ยวกับตัวประมาณค่า cardinality 2014 และปัญหาสำคัญจากที่นี่:
ฟังก์ชั่นใหม่ใน SQL Server 2014 - ส่วนที่ 2 - การประมาณค่าใหม่ของ Cardinality