Saya diuji pada SQL Server 2014 dengan legacy CE dan tidak mendapatkan 9% sebagai perkiraan kardinalitas. Saya tidak dapat menemukan sesuatu yang akurat secara online sehingga saya melakukan beberapa pengujian dan saya menemukan model yang sesuai dengan semua kasus pengujian yang saya coba, tetapi saya tidak dapat memastikan bahwa itu lengkap.
Dalam model yang saya temukan, taksiran diperoleh dari jumlah baris dalam tabel, panjang kunci rata-rata statistik untuk kolom yang difilter, dan terkadang panjang jenis data dari kolom yang difilter. Ada dua formula berbeda yang digunakan untuk estimasi.
Jika FLOOR (panjang kunci rata-rata) = 0 maka rumus estimasi mengabaikan statistik kolom dan membuat estimasi berdasarkan panjang tipe data. Saya hanya menguji dengan VARCHAR (N) sehingga ada kemungkinan bahwa ada formula yang berbeda untuk NVARCHAR (N). Berikut ini rumus untuk VARCHAR (N):
(estimasi baris) = (baris dalam tabel) * (-0.004869 + 0,032649 * log10 (panjang tipe data))
Ini sangat pas, tapi tidak sepenuhnya akurat:
Sumbu x adalah panjang tipe data dan sumbu y adalah jumlah baris yang diperkirakan untuk tabel dengan 1 juta baris.
Pengoptimal kueri akan menggunakan rumus ini jika Anda tidak memiliki statistik pada kolom atau jika kolom memiliki nilai NULL yang cukup untuk mengarahkan panjang kunci rata-rata ke bawah 1.
Misalnya, anggap Anda memiliki tabel dengan baris 150k dengan pemfilteran pada VARCHAR (50) dan tidak ada statistik kolom. Prediksi perkiraan baris adalah:
150000 * (-0.004869 + 0.032649 * log10 (50)) = 7590.1 baris
SQL untuk mengujinya:
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 memberikan perkiraan jumlah baris 7242.47 yang merupakan jenis dekat.
Jika FLOOR (panjang kunci rata-rata)> = 1 maka formula yang berbeda digunakan yang didasarkan pada nilai FLOOR (panjang kunci rata-rata). Berikut adalah tabel dari beberapa nilai yang saya coba:
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%
Jika FLOOR (panjang kunci rata-rata) <6 maka gunakan tabel di atas. Kalau tidak, gunakan persamaan berikut:
(estimasi baris) = (baris dalam tabel) * (-0.003381 + 0,034539 * log10 (LANTAI (panjang kunci rata-rata))))
Yang satu ini memiliki kecocokan yang lebih baik daripada yang lain, tetapi masih belum sepenuhnya akurat.
Sumbu x adalah panjang kunci rata-rata dan sumbu y adalah jumlah baris yang diperkirakan untuk sebuah tabel dengan 1 juta baris.
Untuk memberikan contoh lain, anggaplah Anda memiliki tabel dengan baris 10k dengan panjang kunci rata-rata 5,5 untuk statistik pada kolom yang difilter. Estimasi baris adalah:
10000 * 0,241416 = 241,416 baris.
SQL untuk mengujinya:
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;
Estimasi baris adalah 241,416 yang cocok dengan yang Anda miliki dalam pertanyaan. Akan ada beberapa kesalahan jika saya menggunakan nilai yang tidak ada dalam tabel.
Model-model di sini tidak sempurna tetapi saya pikir mereka menggambarkan perilaku umum dengan cukup baik.