SQL Server 2014'te eski CE ile test ettim ve% 9'luk bir tahmin olarak da almadım. Çevrimiçi olarak doğru bir şey bulamadım, bazı testler yaptım ve denediğim tüm test senaryolarına uygun bir model buldum, ancak tam olduğundan emin olamadım.
Bulduğum modelde, tahmin tablodaki satır sayısından, filtrelenmiş sütunun istatistiklerinin ortalama anahtar uzunluğundan ve bazen de filtrelenmiş sütunun veri türü uzunluğundan elde edilir. Tahmin için kullanılan iki farklı formül vardır.
FLOOR (ortalama anahtar uzunluğu) = 0 ise, tahmin formülü sütun istatistiklerini dikkate almaz ve veri türü uzunluğuna dayalı bir tahmin oluşturur. Sadece VARCHAR (N) ile test ettim, bu yüzden NVARCHAR (N) için farklı bir formül olabilir. VARCHAR (N) için formül:
(satır tahmini) = (tablodaki satırlar) * (-0.004869 + 0.032649 * log10 (veri türünün uzunluğu))
Bu çok güzel bir uyum var, ama tam olarak doğru değil:
X ekseni veri türünün uzunluğu ve y ekseni 1 milyon satır içeren bir tablo için tahmini satır sayısıdır.
Sorgu optimize edici, eğer sütunda istatistiklere sahip değilseniz veya sütun ortalama anahtar uzunluğunu 1'in altına düşürmek için yeterli NULL değerine sahipse bu formülü kullanır.
Örneğin, VARCHAR'da (50) filtre uygulayan ve sütun istatistikleri olmayan 150k satırlık bir tablonuz olduğunu varsayalım. Satır tahmini tahmini:
150000 * (-0,004869 + 0,032649 * log10 (50)) = 7590,1 satır
Sınamak için SQL:
CREATE TABLE X_CE_LIKE_TEST_1 (
STRING VARCHAR(50)
);
CREATE STATISTICS X_STAT_CE_LIKE_TEST_1 ON X_CE_LIKE_TEST_1 (STRING) WITH NORECOMPUTE;
WITH
L0 AS (SELECT 1 AS c UNION ALL SELECT 1),
L1 AS (SELECT 1 AS c FROM L0 A CROSS JOIN L0 B),
L2 AS (SELECT 1 AS c FROM L1 A CROSS JOIN L1 B),
L3 AS (SELECT 1 AS c FROM L2 A CROSS JOIN L2 B),
L4 AS (SELECT 1 AS c FROM L3 A CROSS JOIN L3 B CROSS JOIN L2 C),
NUMS AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS NUM FROM L4)
INSERT INTO X_CE_LIKE_TEST_1 WITH (TABLOCK) (STRING)
SELECT TOP (150000) 'ZZZZZ'
FROM NUMS
ORDER BY NUM;
DECLARE @LastName VARCHAR(15) = 'BA%'
SELECT * FROM X_CE_LIKE_TEST_1
WHERE STRING LIKE @LastName;
SQL Server, 7242.47 bir tahmini satır sayısı verir ve bu yakın bir değerdir.
FLOOR (ortalama anahtar uzunluğu)> = 1 ise, FLOOR (ortalama anahtar uzunluğu) değerini temel alan farklı bir formül kullanılır. İşte denediğim bazı değerlerin tablosu:
1 1.5%
2 1.5%
3 1.64792%
4 2.07944%
5 2.41416%
6 2.68744%
7 2.91887%
8 3.11916%
9 3.29584%
10 3.45388%
FLOOR (ortalama anahtar uzunluğu) <6 ise, yukarıdaki tabloyu kullanın. Aksi takdirde, aşağıdaki denklemi kullanın:
(satır tahmini) = (tablodaki satırlar) * (-0.003381 + 0.034539 * log10 (ZEMİN (ortalama anahtar uzunluğu)))
Bu bir diğerinden daha iyi bir uyuma sahip, ancak yine de tam olarak doğru değil.
X ekseni, ortalama anahtar uzunluğu ve y ekseni, 1 milyon satır içeren bir tablo için tahmini satır sayısıdır.
Başka bir örnek vermek gerekirse, filtrelenmiş sütundaki istatistikler için ortalama anahtar uzunluğu 5.5 olan 10k satırlı bir tablonuz olduğunu varsayalım. Satır tahmini şöyle olur:
10000 * 0.241416 = 241.416 satır.
Sınamak için SQL:
CREATE TABLE X_CE_LIKE_TEST_2 (
STRING VARCHAR(50)
);
WITH
L0 AS (SELECT 1 AS c UNION ALL SELECT 1),
L1 AS (SELECT 1 AS c FROM L0 A CROSS JOIN L0 B),
L2 AS (SELECT 1 AS c FROM L1 A CROSS JOIN L1 B),
L3 AS (SELECT 1 AS c FROM L2 A CROSS JOIN L2 B),
L4 AS (SELECT 1 AS c FROM L3 A CROSS JOIN L3 B CROSS JOIN L2 C),
NUMS AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS NUM FROM L4)
INSERT INTO X_CE_LIKE_TEST_2 WITH (TABLOCK) (STRING)
SELECT TOP (10000)
CASE
WHEN NUM % 2 = 1 THEN REPLICATE('Z', 5)
ELSE REPLICATE('Z', 6)
END
FROM NUMS
ORDER BY NUM;
CREATE STATISTICS X_STAT_CE_LIKE_TEST_2 ON X_CE_LIKE_TEST_2 (STRING)
WITH NORECOMPUTE, FULLSCAN;
DECLARE @LastName VARCHAR(15) = 'BA%'
SELECT * FROM X_CE_LIKE_TEST_2
WHERE STRING LIKE @LastName;
Satır tahmini, soruyla neye uyduğunu belirten 241.416'dır. Tabloda olmayan bir değer kullanırsam bazı hatalar olur.
Buradaki modeller mükemmel değil ama genel davranışı oldukça iyi gösterdiklerini düşünüyorum.