İstatistiklerin otomatik_güncellemesi gerçekleştiğinde bir teknik inceleme . İstatistiklere ilişkin otomatik güncellemeler karşısında dikkat çeken noktalar şunlardır:
- Tablo boyutu 0'dan> 0 satıra gitti (test 1).
- İstatistikler toplandığında tablodaki satır sayısı 500 veya daha azdı ve istatistik nesnesinin önde gelen sütununun colmodctr değeri o zamandan bu yana 500'den fazla değişti (test 2).
- İstatistikler toplandığında tablonun 500'den fazla satırı vardı ve istatistik nesnesinin önde gelen sütununun colmodctr değeri, istatistikler toplandığında tablodaki satır sayısının% 500 + 20'sinden fazla değişti (test 3) .
@JNK, bir yorumda, bir tabloda 1 milyar satırınız varsa, bir güncellemeyi tetiklemek için istatistikteki ilk sütuna 20.000.5000 yazmanız gerektiğini vurguladı.
Aşağıdaki yapıyı ele alalım:
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);
Şimdi istatistik ülkesinde neler olduğunu kontrol edebiliriz.
select *
from sys.stats
where object_id = OBJECT_ID('dbo.test_table')
Bununla birlikte, bunun anlamlı bir istatistik nesnesi olup olmadığını görmek için şunları yapmamız gerekir:
dbcc show_statistics('dbo.test_table',cix_test_table)
Yani bu istatistik güncellenmedi. Çünkü istatistik bir SELECT
oluşum gerçekleşene kadar güncellenmemiş gibi görünüyor ve o zaman bile SELECT
SQL Server'ın histogramının dışında kalması gerekiyor. İşte bunu test etmek için koştum bir test komut dosyası:
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 istatistiklerini körü körüne devre dışı bırakmak yerine, veri kümenizi eğriltme açısından incelemeye çalışırım. Verileriniz önemli ölçüde eğriltme gösteriyorsa, filtrelenmiş istatistikler oluşturmayı ve ardından istatistik güncellemelerini manuel olarak yönetmenin doğru eylem yöntemi olup olmadığına karar vermeniz gerekir .
Eğriliği analiz etmek için incelemek istediğiniz belirli stat / dizin kombinasyonunda DBCC SHOW_STATISTICS(<stat_object>, <index_name>);
(yukarıdaki komut dosyasında) olmadan çalıştırmanız gerekir WITH STAT_HEADER
. Çarpıklığınızı görmenin hızlı bir yolu, histograma (üçüncü sonuç kümesi) bakmak ve varyansınızı kontrol etmek olacaktır EQ_ROWS
. Oldukça tutarlıysa, çarpıklığınız minimumdur. Adımlamak için RANGE_ROWS
sütuna bakarsınız ve buradaki varyansa bakarsınız, çünkü bu her adım arasında kaç satır olduğunu ölçer. Son olarak, [All density]
sonucu DENSITY_VECTOR
(ikinci sonuç kümesinden) alabilir ve (ilk sonuç kümesindeki) [Rows Sampled]
değerle çarpabilir STAT_HEADER
ve bu sütundaki bir sorgu için ortalama beklentinin ne olacağını görebilirsiniz. Bu ortalamayıEQ_ROWS
ve önemli ölçüde değiştiği birçok yer varsa, çarpıklık yaşarsınız.
Eğriliğiniz RANGE_ROWS
olduğunu fark ederseniz, bu değerler hakkında daha iyi tahminler için ek adımlar atabilmeniz için çok yüksek aralıklarda filtrelenmiş istatistikler oluşturmayı düşünmeniz gerekir .
Bu filtrelenmiş istatistikleri yerleştirdikten sonra, istatistikleri manuel olarak güncelleme olasılığına bakabilirsiniz.