Ini adalah whitepaper pada saat auto_update statistik terjadi . Berikut adalah poin penting vis-a-vis pembaruan otomatis untuk statistik:
- Ukuran tabel telah berubah dari 0 hingga> 0 baris (tes 1).
- Jumlah baris dalam tabel ketika statistik dikumpulkan adalah 500 atau kurang, dan colmodctr dari kolom terkemuka objek statistik telah berubah lebih dari 500 sejak saat itu (tes 2).
- Tabel memiliki lebih dari 500 baris ketika statistik dikumpulkan, dan colmodctr dari kolom terkemuka objek statistik telah berubah lebih dari 500 + 20% dari jumlah baris dalam tabel ketika statistik dikumpulkan (uji 3) .
Jadi @JNK membuat poin dalam komentar bahwa jika Anda memiliki 1 miliar baris dalam sebuah tabel, Anda harus memiliki 20.000.5000 tulisan di kolom pertama dalam statistik untuk memicu pembaruan.
Mari kita ambil struktur berikut:
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);
Sekarang kita dapat memeriksa untuk melihat apa yang terjadi di tanah statistik.
select *
from sys.stats
where object_id = OBJECT_ID('dbo.test_table')
Namun, untuk melihat apakah ini adalah objek statistik yang bermakna, kita perlu:
dbcc show_statistics('dbo.test_table',cix_test_table)
Jadi statistik ini belum diperbarui. Itu karena sepertinya statistik tidak diperbarui sampai SELECT
terjadi dan itupun SELECT
harus berada di luar apa yang SQL Server miliki dalam histogramnya. Berikut ini skrip pengujian yang saya jalankan untuk menguji ini:
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
Alih-alih menonaktifkan statistik auto_update secara membabi buta, saya akan mencoba memeriksa set data Anda untuk condong. Jika data Anda menunjukkan kemiringan yang signifikan, maka Anda perlu mempertimbangkan untuk membuat statistik yang difilter dan kemudian memutuskan apakah mengelola pembaruan statistik secara manual adalah tindakan yang benar.
Untuk menganalisis kemiringan Anda perlu menjalankan DBCC SHOW_STATISTICS(<stat_object>, <index_name>);
(dalam skrip di atas tanpa WITH STAT_HEADER
) pada kombinasi stat / indeks tertentu yang ingin Anda periksa. Cara cepat untuk melihat kemiringan Anda adalah dengan melihat histogram (set hasil ketiga) dan memeriksa varians di EQ_ROWS
. Jika itu cukup konsisten maka kemiringan Anda minimal. Untuk meningkatkannya, Anda melihat RANGE_ROWS
kolom dan melihat varians di sana karena ini mengukur berapa banyak baris yang ada di antara setiap langkah. Akhirnya, Anda bisa mengambil [All density]
hasil dari DENSITY_VECTOR
(set hasil kedua) dan mengalikannya dengan [Rows Sampled]
nilai dalam STAT_HEADER
(set hasil pertama) dan melihat apa yang diharapkan rata-rata untuk kueri pada kolom itu. Anda membandingkan rata-rata itu dengan AndaEQ_ROWS
dan jika ada banyak tempat di mana itu bervariasi secara signifikan, maka Anda punya kecenderungan.
Jika ternyata Anda memiliki kemiringan, maka Anda perlu mempertimbangkan untuk membuat beberapa statistik yang difilter pada rentang yang sangat tinggi RANGE_ROWS
sehingga Anda dapat memberikan langkah-langkah tambahan untuk perkiraan yang lebih baik pada nilai-nilai tersebut.
Setelah Anda memiliki statistik yang disaring ini, maka Anda dapat melihat kemungkinan memperbarui statistik secara manual.