พื้นหลัง
ข้อมูลสำหรับวัตถุสถิติถูกรวบรวมโดยใช้คำสั่งของแบบฟอร์ม:
SELECT
StatMan([SC0], [SC1], [SB0000])
FROM
(
SELECT TOP 100 PERCENT
[SC0], [SC1], STEP_DIRECTION([SC0]) OVER (ORDER BY NULL) AS [SB0000]
FROM
(
SELECT
[TextValue] AS [SC0],
[Id] AS [SC1]
FROM [dbo].[Test]
TABLESAMPLE SYSTEM (2.223684e+001 PERCENT)
WITH (READUNCOMMITTED)
) AS _MS_UPDSTATS_TBL_HELPER
ORDER BY
[SC0],
[SC1],
[SB0000]
) AS _MS_UPDSTATS_TBL
OPTION (MAXDOP 1)
คุณสามารถรวบรวมคำแถลงนี้ด้วย Extended Events หรือ Profiler ( SP:StmtCompleted
)
เคียวรีการสร้างสถิติมักเข้าถึงตารางฐาน (แทนที่จะเป็นดัชนีที่ไม่ใช่คลัสเตอร์) เพื่อหลีกเลี่ยงการรวมกลุ่มของค่าที่เกิดขึ้นตามธรรมชาติบนหน้าดัชนีที่ไม่ได้จัดกลุ่ม
จำนวนแถวที่สุ่มตัวอย่างขึ้นอยู่กับจำนวนหน้าทั้งหมดที่เลือกสำหรับการสุ่มตัวอย่าง แต่ละหน้าของตารางจะถูกเลือกหรือไม่ก็ได้ แถวทั้งหมดในหน้าเว็บที่เลือกมีส่วนร่วมในสถิติ
ตัวเลขสุ่ม
SQL Server ใช้ตัวสร้างตัวเลขสุ่มเพื่อตัดสินใจว่าหน้าเว็บมีคุณสมบัติหรือไม่ ตัวสร้างที่ใช้ในอินสแตนซ์นี้คือตัวสร้างตัวเลขสุ่ม Lehmerพร้อมค่าพารามิเตอร์ตามที่แสดงด้านล่าง:
X next = X seed * 7 5 mod (2 31 - 1)
ค่าของคำนวณจากผลรวมของ:Xseed
ส่วนจำนวนเต็มต่ำของbigint
ตารางฐาน( ) partition_id
เช่น
SELECT
P.[partition_id] & 0xFFFFFFFF
FROM sys.partitions AS P
WHERE
P.[object_id] = OBJECT_ID(N'dbo.Test', N'U')
AND P.index_id = 1;
ค่าที่ระบุไว้ในREPEATABLE
ข้อ
- สำหรับตัวอย่าง
UPDATE STATISTICS
ที่REPEATABLE
คุ้มค่าเป็น 1
- ค่านี้ถูกเปิดเผยใน
m_randomSeed
องค์ประกอบของข้อมูลการดีบักภายในของวิธีการเข้าถึงที่แสดงในแผนการดำเนินการเมื่อเปิดใช้งานการตั้งค่าสถานะการสืบค้นกลับ 8666 เป็นต้น<Field FieldName="m_randomSeed" FieldValue="1" />
สำหรับ SQL Server 2012 การคำนวณนี้เกิดขึ้นในsqlmin!UnOrderPageScanner::StartScan
:
mov edx,dword ptr [rcx+30h]
add edx,dword ptr [rcx+2Ch]
โดยที่หน่วยความจำที่[rcx+30h]
มี ID พาร์ติชันต่ำ 32 บิตและหน่วยความจำที่[rcx+2Ch]
มีREPEATABLE
ค่าที่ใช้งาน
ตัวสร้างหมายเลขสุ่มถูกเริ่มต้นในภายหลังในวิธีเดียวกันการโทรsqlmin!RandomNumGenerator::Init
โดยที่คำสั่ง:
imul r9d,r9d,41A7h
... คูณจำนวนเมล็ดด้วย41A7
hex (16807 decimal = 7 5 ) ตามที่แสดงในสมการข้างต้น
ตัวเลขสุ่มไป (สำหรับแต่ละหน้า) จะถูกสร้างขึ้นโดยใช้รหัสพื้นฐานที่เหมือนกัน inlined sqlmin!UnOrderPageScanner::SetupSubScanner
เข้า
Statman
สำหรับStatMan
แบบสอบถามตัวอย่างที่แสดงด้านบนหน้าเดียวกันจะถูกรวบรวมไว้สำหรับคำสั่ง T-SQL:
SELECT
COUNT_BIG(*)
FROM dbo.Test AS T
TABLESAMPLE SYSTEM (2.223684e+001 PERCENT) -- Same sample %
REPEATABLE (1) -- Always 1 for statman
WITH (INDEX(0)); -- Scan base object
สิ่งนี้จะตรงกับผลลัพธ์ของ:
SELECT
DDSP.rows_sampled
FROM sys.stats AS S
CROSS APPLY sys.dm_db_stats_properties(S.[object_id], S.stats_id) AS DDSP
WHERE
S.[object_id] = OBJECT_ID(N'dbo.Test', N'U')
AND S.[name] = N'IX_Test_TextValue';
ตัวเรือนขอบ
ผลลัพธ์อย่างหนึ่งของการใช้ตัวสร้างตัวเลขสุ่ม MINSTD Lehmer คือไม่ควรใช้ค่าเมล็ดเป็นศูนย์และ int.max เนื่องจากจะทำให้อัลกอริทึมสร้างลำดับศูนย์ (เลือกทุกหน้า)
รหัสตรวจจับศูนย์และใช้ค่าจากระบบ 'นาฬิกา' เป็นเมล็ดในกรณีนั้น มันไม่ได้ทำเช่นเดียวกันหากเมล็ดเป็น int.max ( 0x7FFFFFFF
= 2 31 - 1)
เราสามารถสร้างสถานการณ์จำลองนี้ได้เนื่องจากการคำนวณเริ่มต้นของเมล็ดนั้นเป็นผลรวมของ 32 บิตต่ำของ ID พาร์ติชันและREPEATABLE
ค่า REPEATABLE
ค่าที่จะส่งผลให้เมล็ดเป็น int.max และดังนั้นทุกหน้าถูกเลือกสำหรับกลุ่มตัวอย่างคือ
SELECT
0x7FFFFFFF - (P.[partition_id] & 0xFFFFFFFF)
FROM sys.partitions AS P
WHERE
P.[object_id] = OBJECT_ID(N'dbo.Test', N'U')
AND P.index_id = 1;
การทำงานเป็นตัวอย่างที่สมบูรณ์:
DECLARE @SQL nvarchar(4000) =
N'
SELECT
COUNT_BIG(*)
FROM dbo.Test AS T
TABLESAMPLE (0 PERCENT)
REPEATABLE (' +
(
SELECT TOP (1)
CONVERT(nvarchar(11), 0x7FFFFFFF - P.[partition_id] & 0xFFFFFFFF)
FROM sys.partitions AS P
WHERE
P.[object_id] = OBJECT_ID(N'dbo.Test', N'U')
AND P.index_id = 1
) + ')
WITH (INDEX(0));';
PRINT @SQL;
--EXECUTE (@SQL);
ที่จะเลือกทุกแถวในทุก ๆ หน้าTABLESAMPLE
ตามที่ระบุไว้ (แม้แต่ศูนย์เปอร์เซ็นต์)