Thiết lập
Tôi đang gặp một số khó khăn để hiểu một ước tính cardinality. Đây là thiết lập thử nghiệm của tôi:
- phiên bản 2010 của cơ sở dữ liệu Stack Overflow
- Máy chủ SQL 2017 CU15 + GDR (KB4505225) - 14.0.3192.2
- CE mới (mức độ tương thích 140)
Tôi có cái này:
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
Không có chỉ mục hoặc số liệu thống kê không bao gồm trên dbo.Posts
bảng (có một chỉ mục được nhóm trên Id
).
Khi yêu cầu một kế hoạch ước tính cho việc này, "các hàng ước tính" sắp ra dbo.Posts
là 1.934,99:
EXEC #sp_PostsByCommentCount @CommentCount = 51;
Đối tượng thống kê sau được tạo tự động khi tôi yêu cầu kế hoạch ước tính:
DBCC SHOW_STATISTICS('dbo.Posts', [_WA_Sys_00000006_0519C6AF]);
Những điểm nổi bật từ đó là:
- Các thống kê có tỷ lệ mẫu khá thấp là 1,81% (67,796 / 3,744,192)
- Chỉ có 31 bước biểu đồ được sử dụng
- Giá trị "Tất cả mật độ" là
0.03030303
(33 giá trị riêng biệt được lấy mẫu) - Cái cuối cùng
RANGE_HI_KEY
trong biểu đồ là 50, vớiEQ_ROWS
1
Câu hỏi
Vượt qua bất kỳ giá trị nào cao hơn 50 (tối đa và bao gồm 2.147.483.647) dẫn đến ước tính hàng 1.934,99. Tính toán hoặc giá trị nào được sử dụng để tạo ra ước tính này? Nhân tiện, công cụ ước tính cardinality tạo ra ước tính 1 hàng.
Những gì tôi đã thử
Dưới đây là một số lý thuyết tôi đã có, những điều tôi đã thử hoặc các thông tin bổ sung mà tôi có thể khai thác trong khi xem xét điều này.
Mật độ Vector
Ban đầu tôi nghĩ nó sẽ là vector mật độ, giống như khi tôi đã sử dụng OPTION (OPTIMIZE FOR UNKNOWN)
. Nhưng vectơ mật độ cho đối tượng thống kê này là 3.744.192 * 0.03030303 = 113.460, vì vậy không phải vậy.
Sự kiện mở rộng
Tôi đã thử chạy một phiên Sự kiện mở rộng thu thập query_optimizer_estimate_cardinality
sự kiện (mà tôi đã học được từ bài đăng trên blog của Paul White Ước tính Cardinality: Kết hợp thống kê mật độ ) và nhận được các loại tin tức thú vị này:
<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>
Vì vậy, nó xuất hiện CSelCalcAscendingKeyFilter
máy tính đã được sử dụng (người khác nói rằng nó thất bại, bất kể điều đó có nghĩa là gì). Cột này không phải là một khóa, hoặc duy nhất, hoặc nhất thiết phải tăng dần, nhưng bất cứ điều gì.
Thực hiện một số điều khoản của thuật ngữ đó đã dẫn tôi đến một số bài đăng trên blog:
- Joe Sack - Máy tính CSelCalcAsceinatingKeyFilter ,
- Itzik Ben-Gan - Tìm kiếm và bạn sẽ quét Phần II: Phím tăng dần
Các bài đăng này chỉ ra CE mới dựa trên các ước tính biểu đồ bên ngoài này dựa trên sự kết hợp giữa vectơ mật độ và bộ đếm sửa đổi của stat. Thật không may, tôi đã loại trừ vectơ mật độ (tôi nghĩ?!), Và bộ đếm sửa đổi là 0 ( sys.dm_db_stats_properties
dù sao đi nữa).
Cờ truy tìm
Forrest đề nghị tôi bật TF 2363 để có thêm thông tin về quy trình ước tính. Tôi nghĩ rằng điều có liên quan nhất từ đầu ra đó là:
Plan for computation:
CSelCalcAscendingKeyFilter(avg. freq., QCOL: [p].CommentCount)
Selectivity: 0.000516798
Đây là một bước đột phá (cảm ơn, Forrest!): Con 0.000516798
số đó (dường như đã được làm tròn một cách vô ích trong Selectivity="0.001"
thuộc tính XE ở trên) nhân với số lượng hàng trong bảng là ước tính mà tôi đang tìm kiếm (1.934,99).
Có lẽ tôi đang thiếu một cái gì đó rõ ràng, nhưng tôi đã không thể đảo ngược kỹ sư về cách giá trị chọn lọc đó được tạo ra bên trong CSelCalcAscendingKeyFilter
máy tính.