ฉันทดสอบกับ SQL Server 2014 ด้วย CE ดั้งเดิมและไม่ได้รับ 9% เนื่องจากการประเมินความสำคัญเชิงหัวใจเช่นกัน ฉันไม่พบสิ่งที่ถูกต้องทางออนไลน์ดังนั้นฉันจึงทำการทดสอบและฉันพบแบบจำลองที่เหมาะกับกรณีทดสอบทั้งหมดที่ฉันลองใช้ แต่ฉันไม่แน่ใจว่ามันเสร็จสมบูรณ์
ในรูปแบบที่ฉันพบการประมาณนั้นมาจากจำนวนแถวในตารางความยาวคีย์เฉลี่ยของสถิติสำหรับคอลัมน์ที่กรองและบางครั้งความยาวประเภทข้อมูลของคอลัมน์ที่กรอง มีสองสูตรที่แตกต่างกันที่ใช้สำหรับการประเมิน
ถ้า FLOOR (ความยาวคีย์เฉลี่ย) = 0 สูตรการประมาณจะละเว้นสถิติคอลัมน์และสร้างการประมาณตามความยาวประเภทข้อมูล ฉันทดสอบกับ VARCHAR (N) เท่านั้นดังนั้นจึงเป็นไปได้ว่ามีสูตรที่แตกต่างกันสำหรับ NVARCHAR (N) นี่คือสูตรสำหรับ VARCHAR (N):
(การประมาณแถว) = (แถวในตาราง) * (-0.004869 + 0.032649 * log10 (ความยาวของชนิดข้อมูล))
นี่เป็นแบบที่ดีมาก แต่ไม่แม่นยำอย่างสมบูรณ์:
แกน x คือความยาวของชนิดข้อมูลและแกน y คือจำนวนแถวโดยประมาณสำหรับตารางที่มี 1 ล้านแถว
เครื่องมือเพิ่มประสิทธิภาพคิวรีจะใช้สูตรนี้หากคุณไม่มีสถิติในคอลัมน์หรือหากคอลัมน์มีค่า NULL เพียงพอที่จะทำให้ความยาวของคีย์โดยเฉลี่ยต่ำกว่า 1
ตัวอย่างเช่นสมมติว่าคุณมีตารางที่มี 150,000 แถวพร้อมตัวกรองบน VARCHAR (50) และไม่มีสถิติคอลัมน์ การคาดคะเนแถวคือ:
150000 * (-0.004869 + 0.032649 * log10 (50)) = 7590.1 แถว
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 ซึ่งใกล้เคียงที่สุด
ถ้า FLOOR (ความยาวคีย์เฉลี่ย)> = 1 จะใช้สูตรที่แตกต่างกันซึ่งขึ้นอยู่กับค่าของ FLOOR (ความยาวคีย์เฉลี่ย) นี่คือตารางค่าบางอย่างที่ฉันได้ลอง:
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 (ความยาวคีย์เฉลี่ย) <6 ให้ใช้ตารางด้านบน มิฉะนั้นให้ใช้สมการต่อไปนี้:
(การประมาณแถว) = (แถวในตาราง) * (-0.003381 + 0.034539 * log10 (FLOOR (ความยาวคีย์เฉลี่ย))
อันนี้มีขนาดพอดีดีกว่าอีกอันหนึ่ง แต่ก็ยังไม่แม่นยำอย่างสมบูรณ์
แกน x คือความยาวคีย์เฉลี่ยและแกน y คือจำนวนแถวโดยประมาณสำหรับตารางที่มี 1 ล้านแถว
หากต้องการตัวอย่างอื่นสมมติว่าคุณมีตารางที่มี 10k แถวที่มีความยาวคีย์เฉลี่ย 5.5 สำหรับสถิติในคอลัมน์ที่กรอง การประมาณแถวจะเป็น:
10000 * 0.241416 = 241.416 แถว
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;
การประมาณแถวคือ 241.416 ซึ่งตรงกับสิ่งที่คุณมีในคำถาม อาจมีข้อผิดพลาดบางอย่างถ้าฉันใช้ค่าที่ไม่ได้อยู่ในตาราง
แบบจำลองที่นี่ไม่สมบูรณ์ แต่ฉันคิดว่าพวกเขาแสดงให้เห็นถึงพฤติกรรมโดยทั่วไปค่อนข้างดี