Mempersiapkan
Saya mengalami kesulitan memahami perkiraan kardinalitas. Inilah pengaturan pengujian saya:
- versi 2010 dari database Stack Overflow
- SQL Server 2017 CU15 + GDR (KB4505225) - 14.0.3192.2
- CE baru (tingkat kompatibilitas 140)
Saya punya proc ini:
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
Tidak ada indeks atau statistik nonclustered di atas dbo.Posts
meja (ada indeks berkerumun di Id
).
Ketika meminta perkiraan rencana untuk ini, "baris yang diperkirakan" keluar dbo.Posts
adalah 1.934,99:
EXEC #sp_PostsByCommentCount @CommentCount = 51;
Objek statistik berikut secara otomatis dibuat ketika saya meminta perkiraan paket:
DBCC SHOW_STATISTICS('dbo.Posts', [_WA_Sys_00000006_0519C6AF]);
Sorotan dari itu adalah:
- Statistik memiliki tingkat sampel cukup rendah 1,81% (67.796 / 3.744.192)
- Hanya 31 langkah histogram yang digunakan
- Nilai "Semua kepadatan" adalah
0.03030303
(33 nilai berbeda diambil sampelnya) - Terakhir
RANGE_HI_KEY
dalam histogram adalah 50, denganEQ_ROWS
1
Pertanyaan
Melewati nilai apa pun yang lebih tinggi dari 50 (hingga dan termasuk 2.147.483.647) menghasilkan estimasi baris 1.934,99. Perhitungan atau nilai apa yang digunakan untuk menghasilkan estimasi ini? Penaksir kardinalitas warisan menghasilkan perkiraan 1 baris.
Apa yang saya coba
Berikut adalah beberapa teori yang saya miliki, hal-hal yang saya coba, atau sedikit informasi tambahan yang dapat saya gali sambil melihat ke dalam ini.
Vektor Kepadatan
Saya awalnya berpikir itu akan menjadi vektor kerapatan, sama seperti jika saya telah menggunakan OPTION (OPTIMIZE FOR UNKNOWN)
. Tetapi vektor kerapatan untuk objek statistik ini adalah 3.744.192 * 0,03030303 = 113,460, jadi bukan itu.
Acara yang Diperpanjang
Saya mencoba menjalankan sesi Extended Event yang mengumpulkan query_optimizer_estimate_cardinality
acara (yang saya pelajari dari posting blog Paul White Estimasi Kardinalitas: Menggabungkan Statistik Kepadatan ), dan mendapatkan semacam informasi menarik yang menarik:
<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>
Jadi tampaknya CSelCalcAscendingKeyFilter
kalkulator itu digunakan (yang lain mengatakan itu gagal, apa pun artinya). Kolom ini bukan kunci, atau unik, atau harus naik, tetapi apa pun.
Melakukan beberapa Googling dari istilah itu membawa saya ke beberapa posting blog:
- Joe Sack - Kalkulator CSelCalcAscendingKeyFilter ,
- Itzik Ben-Gan - Carilah dan Anda Harus Memindai Bagian II: Tombol Naik
Pos-pos ini menunjukkan basis CE baru yang diestimasi di luar histogram ini pada kombinasi vektor kepadatan dan penghitung modifikasi stat. Sayangnya, saya sudah mengesampingkan vektor kerapatan (saya pikir ?!), dan penghitung modifikasi adalah nol ( sys.dm_db_stats_properties
tetap).
Lacak Bendera
Forrest menyarankan saya mengaktifkan TF 2363 untuk mendapatkan informasi lebih lanjut tentang proses estimasi. Saya pikir hal yang paling relevan dari output itu adalah ini:
Plan for computation:
CSelCalcAscendingKeyFilter(avg. freq., QCOL: [p].CommentCount)
Selectivity: 0.000516798
Ini adalah terobosan (terima kasih, Forrest!): 0.000516798
Angka itu (yang tampaknya tidak membantu dalam Selectivity="0.001"
atribut XE di atas) dikalikan dengan jumlah baris dalam tabel adalah perkiraan yang saya cari (1,934,99).
Saya mungkin kehilangan sesuatu yang jelas, tetapi saya belum dapat merekayasa balik bagaimana nilai selektivitas dihasilkan di dalam CSelCalcAscendingKeyFilter
kalkulator.