Kurmak
Bir kardinalite tahminini anlamakta sorun yaşıyorum. İşte benim test kurulumum:
- Stack Overflow veritabanının 2010 sürümü
- SQL Server 2017 CU15 + GDR (KB4505225) - 14.0.3192.2
- yeni CE (uyumluluk seviyesi 140)
Bu proc var:
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
Tabloda kümelenmemiş dizin veya istatistik yok (üzerinde kümelenmiş bir dizin var Id
).
Bunun için tahmini bir plan isterken, çıkan "tahmini satırlar" dbo.Posts
1.934,99'dur:
EXEC #sp_PostsByCommentCount @CommentCount = 51;
Tahmini planı istediğimde aşağıdaki istatistik nesnesi otomatik olarak oluşturuldu:
DBCC SHOW_STATISTICS('dbo.Posts', [_WA_Sys_00000006_0519C6AF]);
Bundan öne çıkan özellikler:
- İstatistiklerin örnek oranı% 1.81'dir (67.796 / 3.744.192)
- Sadece 31 histogram adımı kullanıldı
- "Tüm yoğunluk" değeri
0.03030303
(33 farklı değer örneklenmiştir) - Son
RANGE_HI_KEY
histogramda ile, 50EQ_ROWS
1 arasında
Soru
50'den yüksek herhangi bir değerin (2,147,483,647'ye kadar ve bu değer dahil) geçmesi 1.934,99 satır tahminiyle sonuçlanır. Bu tahmini oluşturmak için hangi hesaplama veya değer kullanılır? Eski kardinalite tahmincisi bu arada 1 satırlık bir tahmin üretir.
Ne Denedim
İşte sahip olduğum bazı teoriler, denediğim şeyler veya buna bakarken kazabildiğim ek bilgi parçaları.
Yoğunluk Vektörü
Başlangıçta yoğunluk vektörü olacağını düşündüm, sanki kullandığım gibi OPTION (OPTIMIZE FOR UNKNOWN)
. Ancak bu istatistik nesnesinin yoğunluk vektörü 3.744.192 * 0.03030303 = 113.460, bu yüzden bu değil.
Genişletilmiş Etkinlikler
Etkinliği toplayan bir Genişletilmiş Etkinlik oturumu çalıştırmayı denedim query_optimizer_estimate_cardinality
(Paul White'ın blog yazısı Cardinality Tahmini: Yoğunluk İstatistiklerini Birleştirerek öğrendim ) ve bu tür ilginç tidbitler aldım:
<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>
Yani CSelCalcAscendingKeyFilter
hesap makinesi kullanılmış gibi görünüyor (diğeri bunun ne anlama gelirse başarısız olduğunu söylüyor). Bu sütun bir anahtar veya benzersiz veya zorunlu olarak artan değil, her neyse.
Bu terimin bazı Google'larını yapmak beni bazı blog yayınlarına yönlendirdi:
- Joe Sack - CSelCalcAscendingKeyFilter Hesap Makinesi ,
- Itzik Ben-Gan - Ara ve Bölüm II: Tarama Tuşları Tarama
Bu direkler, yeni CE'nin histogram dışındaki tahminleri yoğunluk vektörünün ve statün modifikasyon sayacının bir kombinasyonuna dayandığını göstermektedir. Ne yazık ki, yoğunluk vektörünü zaten dışladım (sanırım ?!) ve değişiklik sayacı sıfırdır ( sys.dm_db_stats_properties
yine de).
İzleme Bayrakları
Forrest , tahmin süreci hakkında daha fazla bilgi almak için TF 2363'ü açmamı önerdi. Bence bu çıktıdan en alakalı şey şudur:
Plan for computation:
CSelCalcAscendingKeyFilter(avg. freq., QCOL: [p].CommentCount)
Selectivity: 0.000516798
Bu bir atılımdır (teşekkürler, Forrest!): Bu 0.000516798
sayı ( Selectivity="0.001"
yukarıdaki XE özelliğinde yararsız bir şekilde yuvarlanmış gibi görünüyor ) tablodaki satır sayısıyla çarpıldığında aradığım tahmin (1,934,99).
Muhtemelen bariz bir şeyi kaçırıyorum, ancak bu seçicilik değerinin CSelCalcAscendingKeyFilter
hesap makinesinin içinde nasıl üretildiğini tersine çeviremedim .