ติดตั้ง
ฉันมีปัญหาในการทำความเข้าใจการประเมินความสำคัญเชิงหัวใจ นี่คือการตั้งค่าการทดสอบของฉัน:
- เวอร์ชัน 2010 ของฐานข้อมูล Stack Overflow
- SQL Server 2017 CU15 + GDR (KB4505225) - 14.0.3192.2
- CE ใหม่ (ระดับความเข้ากันได้ 140)
ฉันมี proc นี้:
USE StackOverflow2010;
GO
CREATE OR ALTER PROCEDURE #sp_PostsByCommentCount
@CommentCount int
AS
BEGIN
SELECT *
FROM dbo.Posts p
WHERE
p.CommentCount = @CommentCount
OPTION (RECOMPILE);
END;
GO
ไม่มีดัชนีหรือสถิติที่ไม่ใช่คลัสเตอร์ในdbo.Posts
ตาราง (มีดัชนีคลัสเตอร์บนId
)
เมื่อถามแผนโดยประมาณสำหรับสิ่งนี้ "แถวโดยประมาณ" ที่ออกมาdbo.Posts
คือ 1,934.99:
EXEC #sp_PostsByCommentCount @CommentCount = 51;
วัตถุสถิติต่อไปนี้ถูกสร้างขึ้นโดยอัตโนมัติเมื่อฉันถามแผนโดยประมาณ:
DBCC SHOW_STATISTICS('dbo.Posts', [_WA_Sys_00000006_0519C6AF]);
ไฮไลท์จากที่:
- สถิติมีอัตราตัวอย่างค่อนข้างต่ำ 1.81% (67,796 / 3,744,192)
- ใช้ขั้นตอนฮิสโตแกรมเพียง 31 ขั้นเท่านั้น
- ค่า "ความหนาแน่นทั้งหมด" คือ
0.03030303
(สุ่มตัวอย่างค่า 33 ค่า) RANGE_HI_KEY
ฮิสโตแกรมสุดท้ายคือ 50 โดยมีEQ_ROWS
1
คำถาม
การส่งค่าใด ๆ ที่สูงกว่า 50 (ขึ้นไปและรวม 2,147,483,647) จะทำให้มีการประมาณการแถว 1,934.99 การคำนวณหรือมูลค่าใดที่ใช้ในการสร้างการประมาณนี้ ตัวประมาณค่า cardinality ดั้งเดิมสร้างการประมาณ 1 แถวโดยวิธีการ
สิ่งที่ฉันได้ลอง
นี่คือทฤษฎีบางอย่างที่ฉันมีสิ่งที่ฉันพยายามหรือข้อมูลเพิ่มเติมที่ฉันสามารถขุดขึ้นมาในขณะที่มองสิ่งนี้
เวกเตอร์ความหนาแน่น
ตอนแรกฉันคิดว่ามันจะเป็นเวกเตอร์ความหนาแน่นเหมือนกับที่ฉันใช้ OPTION (OPTIMIZE FOR UNKNOWN)
ผมเริ่มคิดว่ามันจะเวกเตอร์ความหนาแน่นเช่นเดียวกับถ้าผมใช้แต่เวกเตอร์ความหนาแน่นสำหรับวัตถุสถิตินี้คือ 3,744,192 * 0.03030303 = 113,460 ดังนั้นนั่นไม่ใช่
เหตุการณ์เพิ่มเติม
ฉันลองใช้งานเซสชันเพิ่มเติมในกิจกรรมที่รวบรวมquery_optimizer_estimate_cardinality
เหตุการณ์ (ซึ่งฉันได้เรียนรู้จากโพสต์บล็อกของพอลไวท์ในการประเมิน Cardinality: การรวมสถิติความหนาแน่น ) และได้รับเกร็ดความรู้ที่น่าสนใจเหล่านี้:
<CalculatorList>
<FilterCalculator CalculatorName="CSelCalcColumnInInterval" Selectivity="-1.000"
CalculatorFailed="true" TableName="[p]" ColumnName="CommentCount" />
<FilterCalculator CalculatorName="CSelCalcAscendingKeyFilter" Selectivity="0.001"
TableName="[p]" ColumnName="CommentCount" UseAverageFrequency="true"
StatId="4" />
</CalculatorList>
ดังนั้นจึงปรากฏว่าCSelCalcAscendingKeyFilter
มีการใช้เครื่องคิดเลข (อีกเครื่องหนึ่งบอกว่ามันล้มเหลวไม่ว่าจะเป็นอะไรก็ตาม) คอลัมน์นี้ไม่ใช่กุญแจสำคัญหรือมีเอกลักษณ์หรือจำเป็นต้องขึ้นไป แต่อย่างใด
การทำ Googling ของคำนั้นทำให้ฉันไปที่โพสต์บล็อกบางส่วน:
- โจกระสอบ - The CSelCalcAscendingKeyFilter เครื่องคิดเลข ,
- Itzik Ben-Gan - แสวงหาและคุณจะสแกนส่วนที่สอง: คีย์จากน้อยไปมาก
การโพสต์เหล่านี้บ่งชี้ว่า CE ใหม่ใช้การประมาณนอกกราฟเหล่านี้ในการรวมกันของเวกเตอร์ความหนาแน่นและตัวนับการปรับเปลี่ยนของสถิติ แต่น่าเสียดายที่ฉันได้ตัดเวกเตอร์ความหนาแน่น (ฉันคิดว่า?!) และตัวนับการแก้ไขเป็นศูนย์ (ต่อsys.dm_db_stats_properties
ไป)
ติดตามสถานะ
Forrestแนะนำให้ฉันเปิด TF 2363 เพื่อรับข้อมูลเพิ่มเติมเกี่ยวกับกระบวนการประมาณ ฉันคิดว่าสิ่งที่เกี่ยวข้องที่สุดจากผลลัพธ์นั้นคือ:
Plan for computation:
CSelCalcAscendingKeyFilter(avg. freq., QCOL: [p].CommentCount)
Selectivity: 0.000516798
นี่คือความก้าวหน้า (ขอบคุณ Forrest!): 0.000516798
หมายเลขนั้น(ซึ่งดูเหมือนว่าจะถูกปัดเศษโดยไม่มีประโยชน์ในSelectivity="0.001"
แอตทริบิวต์XE ด้านบน) คูณด้วยจำนวนแถวในตารางคือค่าประมาณที่ฉันได้ค้นหา (1,934.99)
ฉันอาจจะขาดอะไรบางอย่างที่เห็นได้ชัด แต่ฉันไม่สามารถย้อนกลับวิศวกรรมได้ว่าค่าการเลือกเกิดขึ้นในCSelCalcAscendingKeyFilter
เครื่องคิดเลขอย่างไร