นี่คือเอกสารเมื่อ auto_update สถิติเกิดขึ้น นี่คือจุดสำคัญที่ต้องปรับปรุงสถิติสถิติโดยอัตโนมัติ:
- ขนาดตารางลดลงจาก 0 ถึง> 0 แถว (ทดสอบ 1)
- จำนวนแถวในตารางเมื่อรวบรวมสถิติคือ 500 หรือน้อยกว่าและ colmodctr ของคอลัมน์นำของวัตถุสถิติได้เปลี่ยนไปมากกว่า 500 ตั้งแต่นั้นมา (ทดสอบ 2)
- ตารางมีมากกว่า 500 แถวเมื่อรวบรวมสถิติและ colmodctr ของคอลัมน์นำของวัตถุสถิติมีการเปลี่ยนแปลงมากกว่า 500 + 20% ของจำนวนแถวในตารางเมื่อรวบรวมสถิติ (ทดสอบ 3) .
@JNK ชี้ประเด็นในความคิดเห็นว่าถ้าคุณมี 1 พันล้านแถวในตารางคุณจะต้องมี 20,000,5,000 เขียนไปที่คอลัมน์แรกในสถิติเพื่อเริ่มการอัพเดท
ลองมาดูโครงสร้างต่อไปนี้:
CREATE TABLE dbo.test_table (
test_table_id INTEGER IDENTITY(1,1) NOT NULL,
test_table_value VARCHAR(50),
test_table_value2 BIGINT,
test_table_value3 NUMERIC(10,2)
);
CREATE CLUSTERED INDEX cix_test_table ON dbo.test_table (test_table_id, test_table_value);
ตอนนี้เราสามารถตรวจสอบเพื่อดูสิ่งที่เกิดขึ้นในสถิติที่ดิน
select *
from sys.stats
where object_id = OBJECT_ID('dbo.test_table')
อย่างไรก็ตามเพื่อดูว่านี่เป็นวัตถุทางสถิติที่มีความหมายหรือไม่เราจำเป็นต้อง:
dbcc show_statistics('dbo.test_table',cix_test_table)
ดังนั้นสถิตินี้ยังไม่ได้รับการปรับปรุง นั่นเป็นเพราะดูเหมือนว่าสถิติไม่ได้รับการอัปเดตจนกว่าจะมีSELECT
เหตุการณ์เกิดขึ้นและถึงแม้ว่าSELECT
จะต้องอยู่นอกเซิร์ฟเวอร์ SQL ที่มีอยู่ภายในฮิสโตแกรม นี่คือสคริปต์ทดสอบที่ฉันวิ่งไปทดสอบ:
CREATE TABLE test_table (
test_table_id INTEGER IDENTITY(1,1) NOT NULL,
test_table_value VARCHAR(50),
test_table_value2 BIGINT,
test_table_value3 NUMERIC(10,2)
);
CREATE CLUSTERED INDEX cix_test_table ON test_table (test_table_id, test_table_value);
ALTER TABLE test_table ADD CONSTRAINT pk_test_table PRIMARY KEY (test_table_id)
SELECT *
FROM sys.stats
WHERE object_id = OBJECT_ID('dbo.test_table')
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table)
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
declare @test int = 0
WHILE @test < 1
BEGIN
INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
SET @test = @test + 1;
END
SELECT 'one row|select < 1', * FROM test_table WHERE test_table_id < 1;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
SET @test = 1
WHILE @test < 500
BEGIN
INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
SET @test = @test + 1;
END
SELECT '100 rows(add 99)|select < 100',* FROM test_table WHERE test_table_id < 100;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
--get the table up to 500 rows/changes
WHILE @test < 500
BEGIN
INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
SET @test = @test + 1;
END
SELECT '500 rows(add 400)|select < 100',* FROM test_table WHERE test_table_id < 100;
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
SELECT '500 rows(add 400)|select < 500',* FROM test_table WHERE test_table_id < 500;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
--bump it to 501
SET @test = 500;
WHILE @test < 501
BEGIN
INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
SET @test = @test + 1;
END
SELECT '501 rows(add 1)|select < 501',* FROM test_table WHERE test_table_id < 501;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
--bump it to 600
SET @test = 501;
WHILE @test < 600
BEGIN
INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
SET @test = @test + 1;
END
SELECT '600 rows (add 100)|select < 600',* FROM test_table WHERE test_table_id < 600;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
--bump it to 700
SET @test = 600;
WHILE @test < 700
BEGIN
INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
SET @test = @test + 1;
END
SELECT '700 rows (add 100)|select < 700', * FROM test_table WHERE test_table_id < 700;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
--bump it to 1200
SET @test = 700;
WHILE @test < 1200
BEGIN
INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
SET @test = @test + 1;
END
SELECT '1200 rows (add 500)|select < 1200',* FROM test_table WHERE test_table_id < 1200;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
--DROP TABLE test_table
แทนที่จะปิดใช้งานสถิติ auto_update อย่างสุ่ม ๆ ฉันจะลองตรวจสอบชุดข้อมูลของคุณเพื่อหาข้อมูล หากข้อมูลของคุณมีความลาดเอียงอย่างมีนัยสำคัญคุณต้องพิจารณาสร้างสถิติที่กรองแล้วตัดสินใจว่าการจัดการการอัปเดตสถิติด้วยตนเองเป็นวิธีการที่ถูกต้องหรือไม่
หากต้องการวิเคราะห์ความเบ้คุณต้องเรียกใช้DBCC SHOW_STATISTICS(<stat_object>, <index_name>);
(ในสคริปต์ด้านบนโดยไม่มีWITH STAT_HEADER
) ในชุดค่าสถิติ / ดัชนีที่คุณต้องการตรวจสอบ วิธีที่รวดเร็วในลูกตาเอียงของคุณจะดู histogram (ชุดผลลัพธ์ที่สาม) EQ_ROWS
และตรวจสอบความแปรปรวนในของคุณ ถ้ามันค่อนข้างสอดคล้องกันแล้วความเบ้ของคุณก็น้อย ในการเพิ่มระดับขึ้นคุณดูที่RANGE_ROWS
คอลัมน์และดูความแปรปรวนที่มีเนื่องจากการวัดนี้มีจำนวนแถวอยู่ระหว่างแต่ละขั้นตอน สุดท้ายคุณสามารถรับ[All density]
ผลลัพธ์จากDENSITY_VECTOR
(ชุดผลลัพธ์ที่สอง) และคูณด้วย[Rows Sampled]
ค่าในSTAT_HEADER
(ชุดผลลัพธ์แรก) และดูว่าการคาดหวังโดยเฉลี่ยจะเป็นอย่างไรสำหรับแบบสอบถามในคอลัมน์นั้น คุณเปรียบเทียบค่าเฉลี่ยกับของคุณEQ_ROWS
และหากมีหลายสถานที่ที่แตกต่างกันอย่างมีนัยสำคัญแสดงว่าคุณได้รับเอียง
หากคุณพบว่าคุณมีความเบ้คุณต้องพิจารณาสร้างสถิติที่กรองแล้วในช่วงที่มีค่าสูงมากRANGE_ROWS
เพื่อให้คุณสามารถกำหนดขั้นตอนเพิ่มเติมสำหรับการประมาณค่าที่ดีขึ้น
เมื่อคุณมีสถิติที่กรองแล้วคุณสามารถดูความเป็นไปได้ของการอัปเดตสถิติด้วยตนเอง