Ước tính cardinality bên ngoài biểu đồ


14

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.Postsbả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.Postslà 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 chụp màn hình của đầu ra thống kê trong SSMS

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_KEYtrong biểu đồ là 50, với EQ_ROWS1

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_cardinalitysự 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 CSelCalcAscendingKeyFiltermá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:

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_propertiesdù 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.000516798số đó (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 CSelCalcAscendingKeyFiltermáy tính.

Câu trả lời:


13

Dựa trên thử nghiệm của tôi, ước tính số lượng thẻ ngoài giới hạn chỉ đơn giản là căn bậc hai của số hàng, giới hạn bên dưới bởi số hàng được thêm vào kể từ khi cập nhật thống kê cuối cùng và giới hạn ở trên bởi các hàng trung bình trên mỗi giá trị.

Trong trường hợp của bạn, 1,934,99 = SQRT (3744192)

Thiết lập thử nghiệm dưới đây:

--setup
USE TestDB
ALTER DATABASE [TestDB] SET AUTO_UPDATE_STATISTICS OFF
GO

DROP TABLE IF EXISTS dbo.Hist

CREATE TABLE dbo.Hist (
ID int identity primary key,
Num int
)

INSERT dbo.Hist
SELECT TOP 300
(ROW_NUMBER() OVER(ORDER BY(SELECT 1/0)))%3
FROM master..spt_values a
CROSS JOIN master..spt_values b
--Get estimated plan
--don't forget to run right after setup to auto-create stats
SELECT *
FROM dbo.Hist
WHERE Num = 1000
--gradually add rows, then rerun estimate above
INSERT dbo.Hist
SELECT TOP 100
-1
FROM master..spt_values a
--I sure hope you weren't testing this in prod (cleanup)
ALTER DATABASE [TestDB] SET AUTO_UPDATE_STATISTICS ON
GO

Đáng ngạc nhiên là các ước tính hàng thậm chí được tạo ra từ phương pháp này: 20 tại 400 tổng số hàng, 30 tại 900, 40 tại 1600, v.v.

Tuy nhiên, qua 10000, ước tính hàng tối đa là 100, là số lượng hàng trên mỗi giá trị trong các thống kê hiện có. Chỉ thêm 10 hàng sẽ đặt ước tính thành 10, vì sqrt (300)> 10.

Do đó, các ước tính có thể được thể hiện bằng cách sử dụng công thức này:

Estimate = MIN(SQRT(AC), MIN(AR, MC))

Lưu ý rằng nếu số liệu thống kê được lấy mẫu, thì MC không được xem xét. Vì vậy, công thức trở thành:

Estimate = MIN(SQRT(AC), AR))

Ở đâu

  • MC là "số sửa đổi" (# sửa đổi kể từ khi số liệu thống kê được tạo)
  • AC là "số lượng thẻ được điều chỉnh" (# hàng từ số liệu thống kê cộng với MC),
  • AR là hàng trung bình trên mỗi giá trị (# hàng từ thống kê chia cho các giá trị riêng biệt trong cột)

Các công thức cho các ước tính này và các chi tiết khác về máy tính, có thể được tìm thấy trong bài đăng trên blog này: Phân tích Dự toán từ Máy tính CSelCalcAsceinatingKeyFilter

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.